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

Nik*_*nko 22 django django-orm django-south

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

  1. MySQL 5.0作为'默认'数据库,以前是唯一的数据库.
  2. Spatialite作为'gis'数据库,只应用于从shapefile导入区域
  3. South 正在整个项目中使用

现在我已经在我的区域的新应用程序中创建了一个GeoDjango模型.像往常一样,我已经完成了./manage.py schemamigration --initial,当我尝试做的时候./manage.py migrate $my_new_app --database="gis",它失败了django.db.utils.DatabaseError: no such table: south_migrationhistory,这是我猜的正确,因为south_migrationhistory在我的主数据库中.

有没有人有这样的设置经验,可以帮助我吗?

编辑:我已经改变了标题,因为我意识到这个问题实际上不是GeoDjango特有的.

Pie*_*ert 9

我改进了灵魂:

south_migrationhistory在其他数据库中创建表:

./manage.py syncdb --database="my_db_name_for_apps"
Run Code Online (Sandbox Code Playgroud)

您现在可以使用标准:

./manage.py migrate my_app
Run Code Online (Sandbox Code Playgroud)

这是我的实际情况 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
Run Code Online (Sandbox Code Playgroud)

  • 第一个`syncdb`命令将在目标数据库中创建所有应用程序的表,再加上django auth表 - 而不仅仅是您需要的`south_migrationhistory`表. (2认同)

ben*_*ing 9

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

首先,每个人当然应该阅读南方文档中关于多个数据库的极少数几行:)

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

from south.db import dbs
db = dbs['name_of_you_nondefault_db']
Run Code Online (Sandbox Code Playgroud)

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

但要开始,请运行:

python manage.py syncdb
Run Code Online (Sandbox Code Playgroud)

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

python manage.py migrate
Run Code Online (Sandbox Code Playgroud)

该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
Run Code Online (Sandbox Code Playgroud)

现在,你应该运行迁移指定BOTH的app_label和数据库来从south_migrationhistory.

python manage.py migrate name_of_app --database=name_of_you_nondefault_db
Run Code Online (Sandbox Code Playgroud)


Pie*_*ert 5

在我的db_router.py文件中,我只是取消注释'south'我的应用列表中的应用.我启动了一个在数据库中syncdb 创建表.south_migrationhistoryotherdb

./manage.py syncdb --database="otherdb"
Run Code Online (Sandbox Code Playgroud)

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

您现在可以使用标准

./manage.py migrate my_app --database="otherdb"
Run Code Online (Sandbox Code Playgroud)

这是我的 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
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这仍然是一个不完整的解决方案,因为您无法运行./manage.py migrate来迁移这两个数据库.迁移另一个数据库时,South将获取一个数据库的迁移. (2认同)

Tom*_*cki -2

您可能希望在两个数据库中都有South_migrationhistory,因此将south应用程序的syncdb设置为“gist”。那么您的迁移应该会顺利进行。