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

Posted

技术标签:

【中文标题】使用数据库路由器在应用程序 Django 之间共享(mysql)数据库【英文标题】:Sharing (mysql) database between apps Django with Database routers 【发布时间】:2014-03-28 16:33:10 【问题描述】:

我创建了一个 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)

这是我的数据库路由器

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

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

【问题讨论】:

allow_syncdb() 方法应在 db==default 和 model._meta.app_label==myapp 的条件下返回 False。尝试阅读***.com/questions/7360774/…的答案 你确定这里需要两个数据库吗?在应用程序之间共享数据库是正常的普通行为,不需要路由器。 【参考方案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

【讨论】:

【参考方案2】:

我同意丹尼尔·罗斯曼的观点。当您有两个或多个应用程序使用相同的数据库时,使用一个路由器可能会很好。一般来说,每个非默认数据库可能有一个路由器?

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

只要 allow_syncdb 返回 None,Django 根 db 路由器就会尝试 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

【讨论】:

那么我应该输入def allow_syncdb(self,db, model): if db == 'mydb': return model._meta.app_label in ['app1', 'app2'] elif... 之类的内容以避免使用更多路由器吗?那么,我应该把这个文件放在哪里呢? 我会把它放在名为“core”的应用程序中。但是你可能会找到一个不同的地方(取决于你的整体 Django 项目结构)。将文件命名为 routers.py 也是一个好习惯

以上是关于使用数据库路由器在应用程序 Django 之间共享(mysql)数据库的主要内容,如果未能解决你的问题,请参考以下文章

如何在两个 django 应用程序之间共享会话?

如何在 django 服务器和 python websocket 服务器之间共享数据

Django在多个项目之间共享相同用户模型和数据库的最佳方式

Django Channels 是不是使用 ws:// 协议前缀在 Django 视图或 Channels 应用程序之间进行路由?

如何以角度在兄弟组件之间共享数据?

如何在 Django 和 Javascript 之间共享信息?