【问题标题】:Django saving models in different databasesDjango将模型保存在不同的数据库中
【发布时间】:2017-12-27 11:26:15
【问题描述】:

我是 Django 新手。 我在我的项目中创建了两个应用程序:

python3 manage.py startapp app1
python3 manage.py startapp app1

我使用 Mysql 作为数据库,我希望每个应用程序都应该使用不同的模式。

我尝试按照此处描述的步骤进行操作: Sharing (mysql) database between apps Django with Database routers

所以在 settings.py 我定义了 2 个 MySql 模式并保持默认模式和 添加添加 DATABASE_ROUTERS。

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'),
    },
    'mydb1':{
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'APP1DB',
        'USER': 'user1',
        'PASSWORD': '****',
        'HOST': 'localhost',   # Or an IP Address that your DB is hosted on
        'PORT': '3306',
    },
    'mydb2':{
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'APP2DB',
        'USER': 'user1',
        'PASSWORD': '****',
        'HOST': 'localhost',   # Or an IP Address that your DB is hosted on
        'PORT': '3306',
    },
}

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

其他文件: app1/models1.py

from django.db import models

# Create your models here.

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

app2/models2.py

from django.db import models

# Create your models here.

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 'mydb1'
        return None

    def db_for_write(self,model, **hints):
        if model._meta.app_label == 'app1':
            return 'mydb1'
        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 == 'mydb1':
            if model._meta.app_label == 'app1':
                return True
        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 'mydb2'
        return None

    def db_for_write(self,model, **hints):
        if model._meta.app_label == 'app2':
            return 'mydb2'
        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 == 'mydb2':
            if model._meta.app_label == 'app2':
                return True
        elif model._meta.app_label == 'app2':
            return False
        return None

在此之后,我希望当我运行命令 makemigrations 和 migrate 时,我会在 2 个不同的模式中获得 2 个不同的表? 所以:

$ python3 manage.py makemigrations
Migrations for 'app1':
  app1/migrations/0001_initial.py
    - Create model Model1
Migrations for 'app2':
  app2/migrations/0001_initial.py
    - Create model Model2


$ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, app1, app2, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  ...
  Applying sessions.0001_initial... OK

但是除了 django_migrations 在两个模式中都没有创建表。
如果我使用命令:

$ python3 manage.py migrate --database=mydb1

然后在 APP1DB 中创建两个模型表。

mysql> SHOW TABLES;
+----------------------------+
| Tables_in_APP1DB           |
+----------------------------+
| app1_model1                |
| app2_model2                |
| auth_group                 |

那么如何解决呢?

【问题讨论】:

    标签: python mysql django database


    【解决方案1】:

    根据the documentation,数据库路由器可以执行allow_migrate(db, app_label, model_name=None, **hints) 方法以确定是否应该执行某个迁移。自定义数据库路由器的方法总是通过默认数据库路由器django.db.router调用:

    def allow_migrate(self, db, app_label, **hints):
        for router in self.routers:
            try:
                method = router.allow_migrate
            except AttributeError:
                # If the router doesn't have a method, skip to the next one.
                continue
            [...]
        return True
    

    因为您的路由器没有定义这样的方法,它只是在方法结束时返回True,因此将请求的迁移应用到指定的数据库。

    你可以通过定义这个方法来实现跨不同数据库的应用分离:

    class App1DBRouter(object):
        [...]
        def allow_migrate(self, db, app_label, model_name=None, **hints):
            if app_label == 'app1':
                return db == 'mydb1'
            return None
    

    app2 也是如此。

    【讨论】:

    • 要充分发挥作用:1.) 类名应该是 App1DBRouter 2.) 应该返回 db == 'mydb1'
    • @aeliv002 谢谢,已批准。代码是概念性的,但你明白了:-)
    猜你喜欢
    • 2018-12-19
    • 2016-07-07
    • 2021-08-04
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多