Migrate command create all tables on second DB - Django

时间:2018-12-19 11:16:46

标签: django django-migrations django-postgresql

I have an app (ali) on my project (website) and I wanted it to have its own database. The problem is, when I run python manage.py migrate --database=ali, the command recreates all tables within my ali database; whereas the expected result would be to have only the ali_search database.

P.S.: the application seems to be running as expected after I ran some tests. In other words, models from my ali app are being saved on the ali DB. Still, having all these empty tables inside my ali DB is not the correct way to go.

Settings:

# website.settings

...

INSTALLED_APPS = [
    'base.apps.BaseConfig',
    'ali.apps.AliConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.sites',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sitemaps',
    'django_comments',
    'mptt',
    'tagging',
    'zinnia',
]

....

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'website',
        'USER': 'website',
        'PASSWORD': 'website',
        'HOST': 'localhost',
        'PORT': '5432',
    },
    'ali': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'ali',
        'USER': 'ali',
        'PASSWORD': 'ali',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

DATABASE_ROUTERS = [
    'ali.routers.AliRouter',
]

....

Router:

# ali.routers

class AliRouter:
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'ali':
            return 'ali'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'ali':
            return 'ali'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'ali' or \
           obj2._meta.app_label == 'ali':
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label == 'ali':
            return db == 'ali'
        return None

Model:

# ali.models

from django.db import models

class Search(models.Model):

    results = models.IntegerField()

This is what I get by querying my ali DB with \dt:

ali=# \dt
                  List of relations
 Schema |            Name            | Type  | Owner 
--------+----------------------------+-------+-------
 public | ali_search                 | table | ali
 public | auth_group                 | table | ali
 public | auth_group_permissions     | table | ali
 public | auth_permission            | table | ali
 public | auth_user                  | table | ali
 public | auth_user_groups           | table | ali
 public | auth_user_user_permissions | table | ali
 public | django_admin_log           | table | ali
 public | django_comment_flags       | table | ali
 public | django_comments            | table | ali
 public | django_content_type        | table | ali
 public | django_migrations          | table | ali
 public | django_session             | table | ali
 public | django_site                | table | ali
 public | tagging_tag                | table | ali
 public | tagging_taggeditem         | table | ali
 public | zinnia_category            | table | ali
 public | zinnia_entry               | table | ali
 public | zinnia_entry_authors       | table | ali
 public | zinnia_entry_categories    | table | ali
 public | zinnia_entry_related       | table | ali
 public | zinnia_entry_sites         | table | ali
(22 rows)

But what I would really expect is:

ali=# \dt
                  List of relations
 Schema |            Name            | Type  | Owner 
--------+----------------------------+-------+-------
 public | ali_search                 | table | ali
(1 row)

Could it be a problem the fact that the app has the same name as the database (in this case, ali)?

2 个答案:

答案 0 :(得分:2)

None返回allow_migrate()意味着路由器对当前操作没有意见。如果所有配置的路由器都没有意见,则默认为允许该操作。您当前的路由器为None以外的应用返回ali,因此两个数据库都允许进行这些操作。

要禁止在ali数据库上迁移其他应用,在这种情况下,您必须显式返回False,例如:

def allow_migrate(self, db, app_label, model_name=None, **hints):
    if app_label == 'ali':
        return db == 'ali'
    return db == 'default'

现在,您只需为每个数据库运行migrate,而不必指定要迁移的应用程序:

$ python manage.py migrate --database=default
$ python manage.py migrate --database=ali

答案 1 :(得分:0)

对我来说,migrate命令应查看路由以创建表。但似乎并非如此。因此,似乎简单的解决方法是使用migrate参数调用[app_label]。像这样:

python manage.py migrate ali --database=ali