Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop Django to create lot of unnecessary tables

Tags:

python

django

I have two databases defined in my setting.py file.

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': '****',
    }
}

I need to access some tables in source_db which django is not allowing to do so unless I migrate the db. So, once we run command python manage.py migrate --database=source , Django is creating some tables in server db. Since we are not allowed to create tables in server db, is there any way to stop django doing so, or any way to access tables without migrating the db?

This is the list of tables which we don't want to create.

+--------------------------------+
| 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                 |
+--------------------------------+
like image 430
Vikas Gupta Avatar asked Sep 05 '25 03:09

Vikas Gupta


2 Answers

If you want to migrate / create tables in the default database and not source database, then you have to define app and database when you run migrations. Like:

python manage.py migrate dashboard --database=default

This will run migration in the dashboard app and create tables in the default database.

Next thing you want to do is set your source models to non-managed. You do by specifying managed = False in the meta class of the model:

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

From the documentation:

If False, no database table creation or deletion operations will be performed for this model. This is useful if the model represents an existing table or a database view that has been created by some other means.

like image 87
Borut Avatar answered Sep 07 '25 19:09

Borut


Probably nobody was clear about what the author of the question was trying to do. So let me start with the context.

Context

By default, Django uses a database named default. Let's say I have a CustomModel in a CustomApp for which the table should be created in a new database called source_db.
Thus we have two databases: 1)default and 2)source_db.
We want the default tables like auth_group required by apps like django.contrib.auth to be created only in default. The source_db should have and only have tables from CustomApp. How do we do this?

Solution 1: I recommend this method

First, refer to Multiple Databases, the official documentation to understand the routing basics. Give special attention to allow_migrate(). Let me insist, understanding of this documentation is at most important to understand the rest of this solution.

Let's begin:

  1. In your CustomModel, set managed = True in the meta data:

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

    This specifies that the table creation and alteration for this model should be taken care of by Django.

  2. Write your CustomDBRouter for tables in CustomApp. (Refer to Multiple Databases for this). Don't forget to define 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. Go to your settings.py and split the list INSTALLED_APPS as follows:

    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. Now add a new router to project-app(default-app) folder (The folder where you have your settings.py) This router should look like:

    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. Now when adding DefaultDBRouter to DATABASE_ROUTERS in settings.py, make sure that this is the last router in the list. This is at most important since the routers are processed in the order listed.

    DATABASE_ROUTERS = ['customApp.dbRouter.CustomDBRouter', 'project.dbRouter.DefaultDBRouter']
    
  6. Finally, you can migrate using the following commands:

    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' 
    

Solution 2: I don't recommend this

  1. Follow step 1 and 2 of Solution 1.
  2. Now, while doing migrations follow these steps:

    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
    

Since tables like auth_group do not belong to migrations of customApp, they won't be created in the last command. You can add these 3 commands to a shell script to make your job easy. Note that, as the number of apps and databases increase, this method will look dirty. On the other hand, Solution-1 provides a clean way to do this.

like image 32
Jithin Pavithran Avatar answered Sep 07 '25 20:09

Jithin Pavithran