Django在不同数据库中保存模型

时间:2017-07-21 12:02:08

标签: python mysql django database

我是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                 |

那么如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

根据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