Django uses multiple databases, while Django uses Databases

Source: Internet
Author: User

Django uses multiple databases, while Django uses Databases

Some projects may involve the use of multiple databases. The method is simple.

1. Set the DATABASE in settings

For example, you need to use two databases:

DATABASES = {    'default': {        'NAME': 'app_data',        'ENGINE': 'django.db.backends.postgresql',        'USER': 'postgres_user',        'PASSWORD': 's3krit'    },    'users': {        'NAME': 'user_data',        'ENGINE': 'django.db.backends.mysql',        'USER': 'mysql_user',        'PASSWORD': 'priv4te'    }}

In this way, two databases are identified, one alias is default and the other one is user. The database alias can be determined at will.

The default alias is special. When a Model is not selected in a route, the default database is used by default.

Of course, the default value can also be set to NULL:

DATABASES = {    'default': {},    'users': {        'NAME': 'user_data',        'ENGINE': 'django.db.backends.mysql',        'USER': 'mysql_user',        'PASSWORD': 'superS3cret'    },    'customers': {        'NAME': 'customer_data',        'ENGINE': 'django.db.backends.mysql',        'USER': 'mysql_cust',        'PASSWORD': 'veryPriv@ate'    }}

In this way, because no default database exists, you need to select database routes for all models, including the models in the third-party libraries used.

2. Define app_label for the Model that requires database selection

class MyUser(models.Model):    ...    class Meta:        app_label = 'users'

3. Write Database Routers

Database Router is used to determine which Database a Model uses. It mainly defines the following four methods:

db_for_read(Model,** Hints)

Specifies which database the model uses to read data.

db_for_write(Model,** Hints)

Specifies which database the model uses to write data.

allow_relation(Obj1,Obj2,** Hints)

Determine whether an association can be established between obj1 and obj2. It is mainly used for the foreign key and counter to counter operations.

allow_migrate(Db,App_label,Model_name = None,** Hints)

Determine whether the migrate operation can be run on a database with the alias db.

A complete example:

Database settings:

DATABASES = {    'default': {},    'auth_db': {        'NAME': 'auth_db',        'ENGINE': 'django.db.backends.mysql',        'USER': 'mysql_user',        'PASSWORD': 'swordfish',    },    'primary': {        'NAME': 'primary',        'ENGINE': 'django.db.backends.mysql',        'USER': 'mysql_user',        'PASSWORD': 'spam',    },    'replica1': {        'NAME': 'replica1',        'ENGINE': 'django.db.backends.mysql',        'USER': 'mysql_user',        'PASSWORD': 'eggs',    },    'replica2': {        'NAME': 'replica2',        'ENGINE': 'django.db.backends.mysql',        'USER': 'mysql_user',        'PASSWORD': 'bacon',    },}

If you want to achieve the following results:

The Model with the app_label as auth is read and written in auth_db, the rest of the Model is written in primary, and the read is randomly completed in replica1 and replica2.

Auth:

class AuthRouter(object):    """    A router to control all database operations on models in the    auth application.    """    def db_for_read(self, model, **hints):        """        Attempts to read auth models go to auth_db.        """        if model._meta.app_label == 'auth':            return 'auth_db'        return None    def db_for_write(self, model, **hints):        """        Attempts to write auth models go to auth_db.        """        if model._meta.app_label == 'auth':            return 'auth_db'        return None    def allow_relation(self, obj1, obj2, **hints):        """        Allow relations if a model in the auth app is involved.        """        if obj1._meta.app_label == 'auth' or \           obj2._meta.app_label == 'auth':           return True        return None    def allow_migrate(self, db, app_label, model_name=None, **hints):        """        Make sure the auth app only appears in the 'auth_db'        database.        """        if app_label == 'auth':            return db == 'auth_db'        return None

In this way, the Model with the app_label as auth can be read and written in auth_db and can be associated. migrate can only be run in the auth_db database.

Others:

import randomclass PrimaryReplicaRouter(object):    def db_for_read(self, model, **hints):        """        Reads go to a randomly-chosen replica.        """        return random.choice(['replica1', 'replica2'])    def db_for_write(self, model, **hints):        """        Writes always go to primary.        """        return 'primary'    def allow_relation(self, obj1, obj2, **hints):        """        Relations between objects are allowed if both objects are        in the primary/replica pool.        """        db_list = ('primary', 'replica1', 'replica2')        if obj1._state.db in db_list and obj2._state.db in db_list:            return True        return None    def allow_migrate(self, db, app_label, model_name=None, **hints):        """        All non-auth models end up in this pool.        """        return True

In this way, the read is completed randomly in replica1 and replica2, And the write uses primary.

Finally, set in settings:

DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']

You can.

During the migrate operation:

$ ./manage.py migrate$ ./manage.py migrate --database=users

By default, the migrate operation operates the default database. to operate other databases, you can use the -- database option, followed by the database alias.

Corresponding to this, the dbshell, dumpdata, and loaddata commands all have the -- database option.

You can also manually select a route:

Query:

>>> # This will run on the 'default' database.>>> Author.objects.all()>>> # So will this.>>> Author.objects.using('default').all()>>> # This will run on the 'other' database.>>> Author.objects.using('other').all()

Save:

>>> my_object.save(using='legacy_users')

Mobile:

>>> p = Person(name='Fred')>>> p.save(using='first')  # (statement 1)>>> p.save(using='second') # (statement 2)

The above code may cause problems. When p is saved in the first database for the first time, a primary key is generated by default. In this way, when the second database is used for storage, p already has a primary key, this primary key will not cause problems if it is not used, but if it is used previously, it will overwrite the original data.

There are two solutions;

1. Clear the primary key before saving:

>>> p = Person(name='Fred')>>> p.save(using='first')>>> p.pk = None # Clear the primary key.>>> p.save(using='second') # Write a completely new object.

2. Use force_insert

>>> p = Person(name='Fred')>>> p.save(using='first')>>> p.save(using='second', force_insert=True)

Delete:

From which database to delete objects

>>> u = User.objects.using('legacy_users').get(username='fred')>>> u.delete() # will delete from the `legacy_users` database

To transfer an object from the legacy_users database to the new_users database:

>>> user_obj.save(using='new_users')>>> user_obj.delete(using='legacy_users')

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.