如何阻止Django创建大量不必要的表

时间:2017-12-12 08:03:39

标签: python django

我在setting.py文件中定义了两个数据库。

DATABASES = {
    'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'monitoring',
            'USER': 'root',
            'PASSWORD': '',
            'HOST': 'localhost',
            'PORT': '',
    },
    'source' :{
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'source_db',
            'USER': '*****',
            'PASSWORD': '*****',
            'HOST': '*****',
            'PORT': '****',
    }
}

我需要访问source_db中的一些表,除非我迁移数据库,否则django不允许这样做。因此,一旦我们运行命令python manage.py migrate --database=source,Django就会在服务器db中创建一些表。由于我们不允许在服务器数据库中创建表,有没有办法阻止django这样做,还是以任何方式访问表而不迁移数据库?

这是我们不想创建的表列表。

+--------------------------------+
| Tables_in_source_db            |
+--------------------------------+
| auth_group                     |
| auth_group_permissions         |
| auth_permission                |
| auth_user                      |
| auth_user_groups               |
| auth_user_user_permissions     |
| dashboard_monitoring_features  |
| dashboard_monitoring_modelinfo |
| dashboard_monitoring_product   |
| django_admin_log               |
| django_content_type            |
| django_migrations              |
| django_session                 |
+--------------------------------+

4 个答案:

答案 0 :(得分:0)

如果您不想要特定的表格,请删除

'django.contrib.auth`,
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.admin',

dashboard app

来自INSTALLED_APPS

答案 1 :(得分:0)

如果要在default数据库而不是source数据库中迁移/创建表,则必须在运行迁移时定义应用程序和数据库。像:

python manage.py migrate dashboard --database=default

这将在dashboard应用中运行迁移,并在default数据库中创建表。

您要做的下一件事是将source模型设置为non-managed。您可以通过在模型的元类中指定managed = False来完成:

class YourModel(models.Model):
    ... your fields here ...
    class Meta:
        managed = False

来自documentation

  

如果为False,则不会创建或删除数据库表操作   为这个模型执行。如果模型代表一个,这很有用   现有表或由其他人创建的数据库视图   装置

答案 2 :(得分:0)

可能没有人知道问题作者试图做什么。因此,让我从上下文开始。

上下文

默认情况下,Django使用名为default的数据库。假设我在CustomModel中有一个CustomApp,应该在名为source_db的新数据库中为其创建表。
因此,我们有两个数据库:1)default和2)source_db
我们希望仅在auth_group中创建诸如django.contrib.auth之类的应用所需的诸如default之类的默认表。 source_db应该只有CustomApp中的表。我们该怎么做?

解决方案1:我推荐这种方法

首先,请参阅Multiple Databases(官方文档)以了解路由基础。特别注意allow_migrate()。让我坚持认为,了解此文档对于理解此解决方案的其余部分至为重要。

让我们开始吧:

  1. 在您的CustomModel中,在元数据中设置managed = True

    class CustomModel(models.Model):
        # your fields here ...
    
        class Meta:
            managed = True
    

    这指定Django应该照顾该模型的表创建和更改。

  2. CustomDBRouter中的表编写CustomApp。 (有关此问题,请参考Multiple Databases)。不要忘记定义allow_migrate()

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the 'CustomApp' only appear in the 'source_db' database.
        """
        if app_label == 'CustomApp':
            # if app=CustomApp and db=source_db, migrate
            return db == 'source_db'
        return None # No suggestions, ask the next router in the list
    
  3. 转到您的settings.py并按以下方式拆分列表INSTALLED_APPS

    MY_APPS = [                       # List of apps defined by you
        'customApp'
    ]
    INSTALLED_APPS = [                # Full list of apps
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles'
    ] + MY_APPS
    
  4. 现在将新路由器添加到project-app(默认应用)文件夹(您拥有settings.py的文件夹) 该路由器应如下所示:

    from project.settings import MY_APPS
    
    class DefaultDBRouter(object):        
        def allow_migrate(self, db, app_label, model_name=None, **hints):
            """
            If an app is not defined by me, migrate only if database is 'default'
            """
            if app_label not in MY_APPS:
                return db == 'default'
            return False
    
  5. 现在将DefaultDBRouter添加到DATABASE_ROUTERS中的settings.py时,请确保这是列表中的最后一个路由器。这是最重要的,因为路由器按照列出的顺序进行处理。

    DATABASE_ROUTERS = ['customApp.dbRouter.CustomDBRouter', 'project.dbRouter.DefaultDBRouter']
    
  6. 最后,您可以使用以下命令进行迁移:

    python manage.py makemigrations               # Make migrations for all apps
    python manage.py migrate                      # Do migrations to 'default'
    python manage.py migrate --database=source_db # Do migrations to 'source' 
    

解决方案2:我不建议这样做

  1. 遵循解决方案1的步骤1和2。
  2. 现在,在进行迁移时,请遵循以下步骤:

    python manage.py makemigrations  # Make migrations for all apps
    python manage.py migrate         # Do migrations to `default`
    python manage.py migrate customApp --database=source_db 
    # Do migrations to 'source_db' from `customApp` only
    

由于像auth_group这样的表不属于customApp的迁移,因此不会在最后一个命令中创建它们。您可以将这3个命令添加到Shell脚本中以简化工作。请注意,随着应用程序和数据库数量的增加,此方法看起来很脏。另一方面,Solution-1提供了一种干净的方法。

答案 3 :(得分:0)

正在寻找另一个问题,但偶然发现了这个问题。答案是使用数据库路由器。在项目的root_app中创建一个文件(我叫我的model.py)并添加以下设置:

from <app> import models as app_models

class DatabaseRouter(object):
    def db_for_read(self, model, **hints):
        """ Route for when Django is reading the model(s). """

        if model in (
            app_models.<name>,
        ):
            return "project_db"

        return "default"

    def db_for_write(self, model, **hints):
        """ Route for when Django is writing the model(s). """

        if model in (
            app_models.<name>
        ):
            return "project_db"

        return "default"

然后在您的settings.py中,您应该具有:

DATABASES = {
    "default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"},
    "project_db": { ... },
}

以及以下行:

DATABASE_ROUTERS = ("root_app.models.DatabaseRouter",)

您应该可以根据自己的喜好概括以上内容。