📜 ⬆️ ⬇️

Multiple database support

Initially, Django assumed work with only one database (a system constraint including such things as the DATABASE_ * settings group ) . During all this time, the need to support the ability to work with several databases was clearly felt. As part of work on version 1.2 during Google Summer of Code, support for multiple databases was included on the trunk. These innovations are associated with a number of internal changes, as well as several successful extensions to existing database interfaces.

Multi- DB interface

The most noticeable change in Django is that, instead of writing database settings like this:

  DATABASE_ENGINE = "postgresql_psycopg2"
 DATABASE_NAME = "my_big_project"
 DATABASE_USER = "mario"
 DATABASE_PASSWORD = "princess_peach" 

You write the following:
')
  DATABASES = {
     "default": {
         "ENGINE": "django.db.backends.postgresql_psycopg2",
         "NAME": "my_big_project",
         "USER": "mario",
         "PASSWORD": "princess_peach",
     },

     "credentials": {
         "ENGINE": "django.db.backends.oracle",
         "NAME": "users",
     }
 }

Ultimately, all projects will have to be translated into this form, although the old format will be supported in Django up to version 1.4. The only key that has a critical meaning in the DATABASES dictionary is “default” - “default”. If you are using a database, you need to define a “default” database.

Now that you have told Django about all of your databases, you need to find a way to tell Django how to use them. The first interface change in this area is the using () method. using () takes a single parameter database name ( database names are keys of the DATABASES dictionary), and binds the QuerySet to this database. Like any other tool of the QuerySet class, it can be chained if necessary (as, for example, the order_by () method, which updates the results of the first query upon a second query). In fact, it gives you the opportunity to fully control where the data will be read from (and when deftly using the create () , delete () and update () methods even makes it possible to control the recording):

  >>> User.objects.filter (username__startswith = "admin"). Using ("credentials") 

New methods for working with the QuerySet class delete () and save () take an additional argument of using, to which, again, the name of the database is passed.

In addition, a new class method Managers , db_manager () , which also takes the name of the database . Its function is essentially close to the function of the using () method. The main difference is this: instead of returning a QuerySet , it returns a new Manager . The script to use it makes it possible to chain it with those methods of the class Managers that do not return a QuerySet (for example, such as create_user () of the class UserManager ).

DB routers

Using all these methods, you get the opportunity to implement any system that uses multiple databases. Including master-slave replication, partitioning and sharding. However, this will not necessarily be convenient. You will often have to use requests to the method using () in the code, which is not best compatible with the principle of reusable Django applications (for this reason the using option was removed from the Meta model class). In addition, in some cases, the QuerySet class is not fully defined. So, for example, to access the data of the User class, the my_obj.user method will implicitly create a QuerySet , but the using () method will have no place to send the request. This was the reason for the emergence of the concept of a “ database router”. The DB routers receive all the information about the request that you want to complete, and determine which database needs to be accessed. Routers are set in the configuration file as a list of DATABASE_ROUTERS :

  DATABASE_ROUTERS = [
      "path.to.AuthRouter",
      "path.to.MasterSlaveRouter",
  ] 

DATABASE_ROUTERS is set by the list, because the router at any stage can return the value None and then Django will go to the next router from the list. Routers can define the following methods:
The first two methods are obvious; they return the name of the database against which the query is being executed. The allow_relation method is designed to control the reasonableness of requests. Django will not allow you to create deliberately incorrect connections between databases . That is, if you try to create a relationship between two data structures from different databases (for ForeignKey or for ManyToManyField ), using this method, Django will request the necessary confirmation. And the last method allow_syncdb allows you to determine which of the databases will create a specific model.

The Django documentation for working with several databases , as always, gives a lot of practical examples. Including examples that describe how to start applying common patterns with database routers. Supporting multiple databases offers tremendous advantages and greatly expands the scope of Django.

Source: https://habr.com/ru/post/94267/


All Articles