Maison  >  Article  >  interface Web  >  Explication détaillée des étapes pour utiliser plusieurs bases de données Django

Explication détaillée des étapes pour utiliser plusieurs bases de données Django

php中世界最好的语言
php中世界最好的语言original
2018-04-18 13:37:531581parcourir

Cette fois, je vais vous donner une explication détaillée des étapes d'utilisation de Django multi-base de données. Quelles sont les précautions lors de l'utilisation de Django multi-base de données. jetez un oeil.

1. Définissez la BASE DE DONNÉES dans les paramètres

Par exemple, si vous souhaitez utiliser deux bases de données :

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'
  }
}

De cette manière, deux bases de données sont identifiées, l'une avec l'alias par défaut et l'autre avec l'alias utilisateur. L'alias de la base de données peut être déterminé arbitrairement.

L'alias par défaut est spécial Lorsqu'un Modèle n'est pas spécifiquement sélectionné dans la route, la base de données par défaut est utilisée par défaut.

Bien sûr, la valeur par défaut peut également être définie sur vide :

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'
  }
}

De cette façon, comme il n'y a pas de base de données par défaut, le routage de la base de données doit être effectué pour tous les modèles, y compris les modèles des bibliothèques tierces utilisées.

2. Spécifiez app_label

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

pour le modèle qui doit effectuer la sélection de base de données 3. Écrire des routeurs de base de données

Database Router est utilisé pour déterminer quelle base de données un modèle utilise. Il définit principalement les quatre méthodes suivantes :

db_for_read(model, **hints)

Spécifiez la base de données à utiliser pour la lecture du modèle.

db_for_write(model, **hints)

Spécifiez la base de données à utiliser pour écrire le modèle.

allow_relation(obj1, obj2, **hints)

Déterminez si obj1 et obj2 peuvent être associés, principalement utilisés pour les clés étrangères et plusieurs à plusieurs opérations.

allow_migrate(db, app_label, model_name=None, **hints)

Déterminez si l'opération de migration peut être exécutée sur l'alias de base de données db.

Un exemple complet :

Paramètres de la base de données :

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

Si vous souhaitez obtenir les effets suivants :

La lecture et l'écriture du modèle dont app_label est auth sont terminées dans auth_db, le reste de l'écriture du modèle est terminé dans le primaire et la lecture est terminée de manière aléatoire dans réplique1 et réplique2.

authentifiant :

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

De cette manière, la lecture et l'écriture du Modèle dont app_label est auth se terminent dans auth_db, permettant l'association, et la migration ne peut être exécutée que dans la base de données auth_db.

Le reste :

import random
class 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

De cette façon, la lecture s'effectue de manière aléatoire dans les répliques 1 et 2, et l'écriture utilise le primaire.

Enfin paramétrez-le dans les paramètres :

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

C'est ça.

Lors d'une opération de migration :

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

L'opération de migration s'effectue par défaut sur la base de données par défaut. Pour opérer sur d'autres bases de données, vous pouvez utiliser l'option --database, suivie de l'alias de la base de données.

En conséquence, les commandes dbshell, dumpdata et loaddata ont toutes l'option --database.

Vous pouvez également sélectionner l'itinéraire manuellement :

Requête :

>>> # 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()

Enregistrer :

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

Déplacer :

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

Le code ci-dessus posera des problèmes. Lorsque p est enregistré pour la première fois dans la première base de données, une clé primaire sera générée par défaut. De cette façon, lors de l'utilisation de la deuxième base de données pour enregistrer, p a déjà une clé primaire. La clé ne posera pas de problèmes si elle n'est pas utilisée, mais si elle a été utilisée précédemment, les données originales seront écrasées.

Il existe deux solutions ;

1. Effacez la clé primaire avant de sauvegarder :

>>> 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. Utilisez force_insert

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

Supprimer :

À partir de quelle base de données l' objet a-t-il été obtenu et d'où le

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

a-t-il été supprimé ? Si vous souhaitez transférer un objet de la base de données Legacy_users vers la base de données new_users :

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

Je pense que vous maîtrisez la méthode après avoir lu le cas dans cet article. Pour des informations plus intéressantes, veuillez prêter attention aux autres. articles connexes sur le site Web PHP chinois !

Lecture recommandée :

Comment utiliser Babel dans WebStorm ES6

Utiliser React pour restituer des composants vers des nœuds DOM spécifiés

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn