django Multi database configuration tutorial

  • 2020-10-23 20:10:02
  • OfStack

In the django project, it is common to have multiple APP applications in one project. Sometimes you want different APP to connect to different databases and you need to establish multiple database connections.

1. Modify the settings configuration of the project

In ES9en.py, configure the multiple database connection strings that you need to connect to


DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': os.path.join(BASE_DIR, 'sqlite3'),
  },
  'db01': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': os.path.join(BASE_DIR, 'db_01'),
  },
  'db02': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': os.path.join(BASE_DIR, 'db_02'),
  },
}

Suppose we now use three databases, one default default library, one db01 and db02

2. Set the routing rules of the database

Configure DATABASE_ROUTERS in ES21en.py


DATABASE_ROUTERS = ['Prject.database_router.DatabaseAppsRouter']

Project: Name of the django project established (project_name)

database_router: Defines the routing rule es36EN_router.py file name, which you can define yourself

DatabaseAppsRouter: The name of the routing rule class defined in the database_router.py file

3. Set the database routing table corresponding to APP

Each APP to connect to which database, need to do the matching setting, in the settings.py file to do the following configuration:


DATABASE_APPS_MAPPING = {
  # example:
  # 'app_name':'database_name',
  'app02': 'db02',
  'app01': 'db01',
  'admin': 'db01',
  'auth': 'db01',
  'contenttypes': 'db01',
  'sessions': 'db01',
}

The above app01 and app02 are the names of APP in the project and are assigned to the database of db01 and db02 respectively.

In order to create django's own tables in your own database, you can specify: admin, auth, contenttypes, sessions to the set database, otherwise it will be automatically created in the default (default) database

4. Create database routing rules

Create es75EN_ES76en.py file under the project project root path (with settings.ES74en file level 1) :


from django.conf import settings
DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING
class DatabaseAppsRouter(object):
  """
  A router to control all database operations on models for different
  databases.
  In case an app is not set in settings.DATABASE_APPS_MAPPING, the router
  will fallback to the `default` database.
  Settings example:
  DATABASE_APPS_MAPPING = {'app1': 'db1', 'app2': 'db2'}
  """
  def db_for_read(self, model, **hints):
    """"Point all read operations to the specific database."""
    if model._meta.app_label in DATABASE_MAPPING:
      return DATABASE_MAPPING[model._meta.app_label]
    return None
  def db_for_write(self, model, **hints):
    """Point all write operations to the specific database."""
    if model._meta.app_label in DATABASE_MAPPING:
      return DATABASE_MAPPING[model._meta.app_label]
    return None
  def allow_relation(self, obj1, obj2, **hints):
    """Allow any relation between apps that use the same database."""
    db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
    db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
    if db_obj1 and db_obj2:
      if db_obj1 == db_obj2:
        return True
      else:
        return False
    return None
  def allow_syncdb(self, db, model):
    """Make sure that apps only appear in the related database."""
    if db in DATABASE_MAPPING.values():
      return DATABASE_MAPPING.get(model._meta.app_label) == db
    elif model._meta.app_label in DATABASE_MAPPING:
      return False
    return None
  def allow_migrate(self, db, app_label, model=None, **hints):
    """
    Make sure the auth app only appears in the 'auth_db'
    database.
    """
    if db in DATABASE_MAPPING.values():
      return DATABASE_MAPPING.get(app_label) == db
    elif app_label in DATABASE_MAPPING:
      return False
    return None

5. Models creates samples

When you create models for a data table in your respective APP, you must specify the app_label name for the table. If you do not specify app_label, you will create the database name configured in default.

As follows:

Create models under app01


class Users(models.Model):
  name = models.CharField(max_length=50)
  passwd = models.CharField(max_length=100)
  def __str__(self):
    return "app01 %s " % self.name
  class Meta:
    app_label = "app01"

Create models under app02


class Users(models.Model):
  username = models.CharField(max_length=100)
  password = models.CharField(max_length=50)
  age = models.IntegerField()
  def __str__(self):
    return "app02 %s" % self.username
  class Meta:
    app_label = "app02"
class Book(models.Model):
  user = models.ForeignKey("Users", on_delete=models.CASCADE)
  bookname = models.CharField(max_length=100)
  def __str__(self):
    return "%s: %s" % (self.user.username, self.bookname)
  class Meta:
    app_label = "app02"

Create models in app03 without specifying app_label, create under default


class Users(models.Model):  
  username = models.CharField(max_length=100)

6. Generate data tables

When creating the generated table using migrate of django, the database parameter should be added. If not added, the table in models of APP without specifying app_label will be created into the database specified by default, such as:

Create the table in models under app01 into the database "db_01" of db01


./ manage.py migrate --database=db01    

Create the table in models under app02 into the database "db_02" of db02


./ manage.py migrate --database=db02

Create the table in models under app03 into default's database "sqlite3"


./ manage.py migrate

After the above creation is completed, all other operations such as create, query, delete and so on and ordinary 1 operation is ok, need not use similar again


DATABASE_ROUTERS = ['Prject.database_router.DatabaseAppsRouter']
0

Let's do it this way.


Related articles: