Maison  >  Article  >  interface Web  >  Introduction à la façon dont Django utilise plusieurs méthodes de base de données

Introduction à la façon dont Django utilise plusieurs méthodes de base de données

巴扎黑
巴扎黑original
2017-09-07 10:17:081507parcourir

Certains projets peuvent impliquer l'utilisation de plusieurs bases de données, et la méthode est très simple. Ensuite, cet article vous présentera la méthode d'utilisation de plusieurs bases de données dans Django. Les amis qui en ont besoin peuvent s'y référer

Certains projets peuvent impliquer l'utilisation de plusieurs bases de données. La méthode est très simple.

1. Définissez 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, vous devez définir à tous les modèles, y compris Le modèle de la bibliothèque tierce est utilisé pour effectuer la sélection de routage de la base de donné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. Écrivez les 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écifie quelle base de données le modèle utilise pour lire.

db_for_write(model, **hints)

Spécifie dans quelle base de données le modèle doit être écrit.

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étermine si l'opération de migration peut être exécutée sur la base de données avec l'alias db.

Un exemple complet :

Paramètres de la base de données :


DATABASES = {
  &#39;default&#39;: {},
  &#39;auth_db&#39;: {
    &#39;NAME&#39;: &#39;auth_db&#39;,
    &#39;ENGINE&#39;: &#39;django.db.backends.mysql&#39;,
    &#39;USER&#39;: &#39;mysql_user&#39;,
    &#39;PASSWORD&#39;: &#39;swordfish&#39;,
  },
  &#39;primary&#39;: {
    &#39;NAME&#39;: &#39;primary&#39;,
    &#39;ENGINE&#39;: &#39;django.db.backends.mysql&#39;,
    &#39;USER&#39;: &#39;mysql_user&#39;,
    &#39;PASSWORD&#39;: &#39;spam&#39;,
  },
  &#39;replica1&#39;: {
    &#39;NAME&#39;: &#39;replica1&#39;,
    &#39;ENGINE&#39;: &#39;django.db.backends.mysql&#39;,
    &#39;USER&#39;: &#39;mysql_user&#39;,
    &#39;PASSWORD&#39;: &#39;eggs&#39;,
  },
  &#39;replica2&#39;: {
    &#39;NAME&#39;: &#39;replica2&#39;,
    &#39;ENGINE&#39;: &#39;django.db.backends.mysql&#39;,
    &#39;USER&#39;: &#39;mysql_user&#39;,
    &#39;PASSWORD&#39;: &#39;bacon&#39;,
  },
}
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.

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 == &#39;auth&#39;:
      return &#39;auth_db&#39;
    return None
  def db_for_write(self, model, **hints):
    """
    Attempts to write auth models go to auth_db.
    """
    if model._meta.app_label == &#39;auth&#39;:
      return &#39;auth_db&#39;
    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 == &#39;auth&#39; or \
      obj2._meta.app_label == &#39;auth&#39;:
      return True
    return None
  def allow_migrate(self, db, app_label, model_name=None, **hints):
    """
    Make sure the auth app only appears in the &#39;auth_db&#39;
    database.
    """
    if app_label == &#39;auth&#39;:
      return db == &#39;auth_db&#39;
    return None
De cette façon, la lecture et l'écriture du Modèle dont app_label est auth se terminent dans auth_db, et les associations sont autorisées . Migrate est uniquement 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([&#39;replica1&#39;, &#39;replica2&#39;])
  def db_for_write(self, model, **hints):
    """
    Writes always go to primary.
    """
    return &#39;primary&#39;
  def allow_relation(self, obj1, obj2, **hints):
    """
    Relations between objects are allowed if both objects are
    in the primary/replica pool.
    """
    db_list = (&#39;primary&#39;, &#39;replica1&#39;, &#39;replica2&#39;)
    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 se fait de manière aléatoire dans la réplique1 et la réplique2, et l'écriture utilise le primaire.

Enfin, définissez-le dans les paramètres :


DATABASE_ROUTERS = [&#39;path.to.AuthRouter&#39;, &#39;path.to.PrimaryReplicaRouter&#39;]
et c'est tout.

Lors de l'exécution d'une opération de migration :


$ ./manage.py migrate
$ ./manage.py migrate --database=users
L'opération de migration opère 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. 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 manuellement l'itinéraire :

Requête :


>>> # This will run on the &#39;default&#39; database.
>>> Author.objects.all()
>>> # So will this.
>>> Author.objects.using(&#39;default&#39;).all() 
>>> # This will run on the &#39;other&#39; database.
>>> Author.objects.using(&#39;other&#39;).all()
Enregistrer :


>>> my_object.save(using=&#39;legacy_users&#39;)
Déplacer :


>>> p = Person(name=&#39;Fred&#39;)
>>> p.save(using=&#39;first&#39;) # (statement 1)
>>> p.save(using=&#39;second&#39;) # (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, il générera par défaut une clé primaire de sorte que lors de l'enregistrement dans la deuxième base de données, p ait déjà une clé primaire. Cette clé primaire 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 d'origine seront écrasées. .

Il existe deux solutions :

1. Effacez la clé primaire avant de sauvegarder :


>>> p = Person(name=&#39;Fred&#39;)
>>> p.save(using=&#39;first&#39;)
>>> p.pk = None # Clear the primary key.
>>> p.save(using=&#39;second&#39;) # Write a completely new object.
2. Utilisez force_insert


>>> p = Person(name=&#39;Fred&#39;)
>>> p.save(using=&#39;first&#39;)
>>> p.save(using=&#39;second&#39;, force_insert=True)
pour supprimer :

De quelle base de données l'objet a été obtenu et où supprimer


>>> u = User.objects.using(&#39;legacy_users&#39;).get(username=&#39;fred&#39;)
>>> u.delete() # will delete from the `legacy_users` database
Si vous souhaitez transférer un objet de la base de données Legacy_users vers la base de données new_users :


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