应用程序Django与数据库路由器之间共享(mysql)数据库

时间:2014-02-26 03:52:39

标签: mysql django django-models django-database

我创建了一个django项目,然后创建了两个应用程序app1和app2。我希望这两个应用程序共享一个mysql数据库('nameofDB'到mysql,'mydb'到django)。我在settings.py中将数据库添加到DATABASES,并为每个应用创建了一个dbrouter文件,并将每个路由器添加到DATABASE_ROUTERS。另外在settings.py中将每个应用添加到INSTALLED_APPS。

我的问题是当我尝试制作

python manage.py syncdb --database=mydb

因为它不同步两个应用程序(仅限app1)。它说:

Creating tables ...
Creating table app1_model1
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)

这是我的settings.py:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app1',
    'app2',
)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'mydb':{
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'nameofDB',
        'USER':'username',
        'PASSWORD':'password',
    }
}

DATABASE_ROUTERS = ['app1.dbRouter.App1DBRouter', 'app2.dbRouter.App2DBRouter']

这是我的模特:

APP1 / models.py:

class Model1(models.Model):
    name = models.CharField(max_length=100)

APP2 / models.py:

class Model2(models.Model):
    name = models.CharField(max_length=100)

以下是我的dbrouters

APP1 / dbRouter.py

class App1DBRouter(object):
    def db_for_read(self,model, **hints):
        if model._meta.app_label == 'app1':
            return 'mydb'
        return None
    def db_for_write(self,model, **hints):
        if model._meta.app_label == 'app1':
            return 'mydb'
        return None
    def allow_relation(self,obj1, obj2, **hints):
        if obj1._meta.app_label == 'app1' and \
           obj2._meta.app_label == 'app1':
           return True
        return None
    def allow_syncdb(self,db, model):
        if db == 'mydb':
            return model._meta.app_label == 'app1'
        elif model._meta.app_label == 'app1':
            return False
        return None

APP2 / dbRouter.py

class App2DBRouter(object):
    def db_for_read(self,model, **hints):
        if model._meta.app_label == 'app2':
            return 'mydb'
        return None
    def db_for_write(self,model, **hints):
        if model._meta.app_label == 'app2':
            return 'mydb'
        return None
    def allow_relation(self,obj1, obj2, **hints):
        if obj1._meta.app_label == 'app2' and \
           obj2._meta.app_label == 'app2':
           return True
        return None
    def allow_syncdb(self,db, model):
        if db == 'mydb':
            return model._meta.app_label == 'app2'
        elif model._meta.app_label == 'app2':
            return False
        return None

它出了什么问题?我该怎么办?提前致谢! :)

2 个答案:

答案 0 :(得分:1)

也许之前创建了app2_model2,检查一下!

你可以这样做:

<强> settings.py

DATABASE_APPS_MAPPING = {'app1': 'mydb', 'app2': 'mydb'}
DATABASE_ROUTERS = ['path.router.DatabaseAppsRouter']

<强> router.py

from django.conf import settings

class DatabaseAppsRouter(object):
    """
    A router to control all database operations on models for different
    databases.

    In case an app is not set in settings.DATABASE_APPS_MAPPING, the router
    will fallback to the `default` database.

    Settings example:

    DATABASE_APPS_MAPPING = {'app1': 'db1', 'app2': 'db2'}
    """

    def db_for_read(self, model, **hints):
        """Point all read operations to the specific database."""
        if settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
            return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
        return None

    def db_for_write(self, model, **hints):
        """Point all write operations to the specific database."""
        if settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
            return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """Allow any relation between apps that use the same database."""
        db_obj1 = settings.DATABASE_APPS_MAPPING.get(obj1._meta.app_label)
        db_obj2 = settings.DATABASE_APPS_MAPPING.get(obj2._meta.app_label)
        if db_obj1 and db_obj2:
            if db_obj1 == db_obj2:
                return True
            else:
                return False
        return None

    def allow_syncdb(self, db, model):
        """Make sure that apps only appear in the related database."""

        if db in settings.DATABASE_APPS_MAPPING.values():
            return settings.DATABASE_APPS_MAPPING.get(model._meta.app_label) == db
        elif settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
            return False
        return None

答案 1 :(得分:1)

我同意丹尼尔罗斯曼的观点。当你有两个或多个使用同一个数据库的应用程序时,你可以使用一个路由器。通常每个非默认数据库可能有一个路由器吗?

但如果你真的需要两台路由器就是一个解决方案。

只要allow_syncdb返回None,Django根数据库路由器就会尝试从DATABASE_ROUTERS开始的所有路由器。因此,App1DBRouter.allow_syncdb需要为model._meta.app_label =='app2'和db =='mydb'返回None(而不是False)。这样,App2DBRouter.allow_syncdb将有机会被调用。

我让你的syncdb处理以下更改

class App1DBRouter(object):
    ...
    def allow_syncdb(self,db, model):
        if db == 'mydb':
            if model._meta.app_label == 'app1':
                return True
        elif model._meta.app_label == 'app1':
            return False
        return None

class App2DBRouter(object):
    ...
    def allow_syncdb(self,db, model):
        if db == 'mydb':
            if model._meta.app_label == 'app2':
                return True
            else:
                return False
        elif model._meta.app_label == 'app2':
            return False
        return None