是否可以使用多个数据库和南方?

时间:2011-08-11 16:09:54

标签: django django-south django-orm

我目前的项目正在扩展地理位置,因此我正在尝试集成GeoDjango并为初学者导入一些shapefile。我的设置包括以下内容:

  1. MySQL 5.0作为'默认'数据库,以前是唯一的数据库。
  2. Spatialite as'gis'数据库,只应用于从shapefile导入区域
  3. South正在整个项目中使用
  4. 现在我已经在我的区域的新应用程序中创建了一个GeoDjango模型。像往常一样,我已经完成了./manage.py schemamigration --initial,当我尝试./manage.py migrate $my_new_app --database="gis"时,它失败了django.db.utils.DatabaseError: no such table: south_migrationhistory,我认为这是正确的,因为south_migrationhistory在我的主数据库中。

    有没有人对此类设置有任何经验并可以帮助我?

    编辑:我已经更改了标题,因为我意识到这个问题实际上并不是特定于Ge​​oDjango的。

7 个答案:

答案 0 :(得分:9)

我的灵魂得到了改善:

在另一个数据库中创建表south_migrationhistory

./manage.py syncdb --database="my_db_name_for_apps"

您现在可以使用标准:

./manage.py migrate my_app

这是我的实际db_router.py

# -*- coding: UTF-8 -*-
apps =['app1', 'app2' ]    
db_name = 'my_db_name_for_apps'

class sh_router(object):
    """A router to control all database operations on models from applications in apps"""

    def db_for_read(self, model, **hints):
        """Point all operations on apps models to db_name"""
        if model._meta.app_label in apps :
            return db_name
        return None

    def db_for_write(self, model, **hints):
        """Point all operations on apps models to db_name"""
        if model._meta.app_label in apps:
            return db_name
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """Allow any relation if a model in apps is involved"""
        if obj1._meta.app_label in apps or obj2._meta.app_label in apps:
            return True
        return None

    def allow_syncdb(self, db, model):
        """Make sure the apps only appears on the db_name db"""
        if model._meta.app_label in ['south']:
            return True
        if db == db_name:
            return model._meta.app_label in apps
        elif model._meta.app_label in apps:
            return False
        return None

答案 1 :(得分:9)

我发现所有答案都有些不准确,因此,这是一个总结。

首先,每个人当然应该阅读the South documentation中关于多个数据库的极少数几行:)

执行此操作的方法是手动编辑迁移文件以指向正确的数据库。最简单的方法是将其添加到所有文件的顶部:

from south.db import dbs
db = dbs['name_of_you_nondefault_db']

基本原因是South没有从数据库路由器中获取数据库的名称。这个功能根本没有实现,可能永远不会出现Django 1.7。

但要开始工作,请运行:

python manage.py syncdb

现在,你有了south_migrationhistory表。然后要迁移您的特殊数据库,请执行以下操作:

python manage.py migrate

south_migrationhistory将 NOT 在每个数据库中创建,只有默认数据库。因此,迁移历史可以保持集中。

具有相同应用程序的不同副本的多个数据库

如果您需要在同一个应用程序中迁移多个数据库,则不应使用单一迁移历史记录。

相反,像这样创建south_migrationhistory:

python manage.py sql south | PGOPTIONS="-c search_path=NAME_OF_YOUR_SCHEMA_TO_CREATE_IN" python manage.py dbshell --database=name_of_you_nondefault_db

现在,您应该运行迁移,指定 BOTH app_label和数据库,以便从中获取south_migrationhistory。

python manage.py migrate name_of_app --database=name_of_you_nondefault_db

答案 2 :(得分:5)

在我的db_router.py文件中,我只是取消注释我的应用列表中的'south'应用。 我启动syncdb以在south_migrationhistory数据库中创建表otherdb

./manage.py syncdb --database="otherdb"

接下来再次评论我的应用列表中的'south'应用。

您现在可以使用标准

./manage.py migrate my_app --database="otherdb"

这是我的db_router.py

#-*- coding: UTF-8 -*-

apps =['app1',
     'app2',
     'south', # <<<---------------- Comment / Uncomment here
   ]

db_name = 'otherdb'

class sh_router(object):
"""A router to control all database operations on models from applications in apps"""

  def db_for_read(self, model, **hints):
    """Point all operations on apps models to db_name"""
    if model._meta.app_label in apps :
        return db_name
    return None

  def db_for_write(self, model, **hints):
    """Point all operations on apps models to db_name"""
    if model._meta.app_label in apps:
        return db_name
    return None

  def allow_relation(self, obj1, obj2, **hints):
    """Allow any relation if a model in apps is involved"""
    if obj1._meta.app_label in apps or obj2._meta.app_label in apps:
        return True
    return None

  def allow_syncdb(self, db, model):
    """Make sure the apps only appears on the db_name db"""
    if db == db_name:
        return model._meta.app_label in apps
    elif model._meta.app_label in apps:
        return False
    return None

答案 3 :(得分:1)

正如Tomasz所说,你必须同步dbdb你的“gis”数据库,以便创建所有必需的表,包括south_migrationhistory。

./manage.py syncdb --database=gis

答案 4 :(得分:1)

似乎Django 1.7在其数据库路由器类中有allow_migrate()来解决这个问题。

对于早期的Djangos:

  • 您需要在任何需要迁移的数据库中使用south_migrationhistory
  • 定期syncdb将所有常规auth_ *等表放在default db
  • 会将south_migrationhistory放入default
  • 不要syncdb --database=other,这将复制所有auth_ *等。 other
  • 中的表格
  • 而是将south_migrationhistory表格从default复制到other,例如

    sqlite3 main.sqlite ".sc south_migrationhistory" | sqlite3 other.sqlite

    或等效的pg_dump命令或其他

  • 然后使用migrate --database=other

至少这会将所有内容都放在正确的位置,直到您迁移到1.7: - )

答案 5 :(得分:0)

我知道线程已经过时了,但是我遇到了同样的问题,谷歌给了我那个帖子。

首先,您需要更改数据迁移的方式:

    def forwards(self, orm):
    "Write your forwards methods here."                               
        obj = orm.Obj()
        obj.name = 'my name'
        obj.save(using=db.db_alias)

变量db.db_alias包含要使用的db的名称,因此您需要使用'usgin'执行所有操作并使用db.db_alias作为db名称。

然后你用它来运行你的迁移 ./mange migrate App --database = DB_NAME

在schemamigration的情况下,直接使用db.function就像南方一样。

答案 6 :(得分:-2)

您可能希望在两个数据库中都使用south_migrationhistory,因此对于南应用程序,syncdb为“gist”。然后你的迁移就可以了。