Heim  >  Artikel  >  Web-Frontend  >  Einführung in die Verwendung mehrerer Datenbankmethoden durch Django

Einführung in die Verwendung mehrerer Datenbankmethoden durch Django

巴扎黑
巴扎黑Original
2017-09-07 10:17:081512Durchsuche

Einige Projekte erfordern möglicherweise die Verwendung mehrerer Datenbanken, und die Methode ist sehr einfach. Als Nächstes stellt Ihnen dieser Artikel die Methode zur Verwendung mehrerer Datenbanken in Django vor.

Einige Projekte erfordern möglicherweise die Verwendung mehrerer Datenbanken. Die Methode ist sehr einfach.

1. Stellen Sie DATENBANK in den Einstellungen ein

Zum Beispiel, wenn Sie zwei Datenbanken verwenden möchten:


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

Auf diese Weise werden zwei Datenbanken identifiziert, eine mit dem Alias-Standard und die andere mit dem Alias-Benutzer. Der Alias ​​der Datenbank kann beliebig bestimmt werden.

Der Alias ​​„Default“ ist etwas ganz Besonderes. Wenn ein Modell nicht speziell in der Route ausgewählt ist, wird standardmäßig die Standarddatenbank verwendet.

Natürlich kann die Standardeinstellung auch auf leer gesetzt werden:


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

Auf diese Weise müssen Sie eine Standarddatenbank festlegen, da keine Standarddatenbank vorhanden ist Es gilt für alle Modelle, einschließlich des Modells in der Bibliothek eines Drittanbieters, das zur Auswahl des Datenbank-Routings verwendet wird.

2. Geben Sie app_label an


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

3. Datenbank-Router schreiben

Datenbank-Router wird verwendet Bestimmen Sie, welche Datenbank ein Modell verwendet. Es definiert hauptsächlich die folgenden vier Methoden:

db_for_read(model, **hints)

Gibt an, welche Datenbank das Modell zum Lesen verwendet.

db_for_write(model, **hints)

Gibt an, in welche Datenbank das Modell geschrieben werden soll.

allow_relation(obj1, obj2, **hints)

Bestimmen Sie, ob obj1 und obj2 verknüpft werden können. Wird hauptsächlich für Fremdschlüssel und viele zu viele Operationen verwendet.

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

Bestimmt, ob der Migrationsvorgang auf dem Datenbankalias db ausgeführt werden kann.

Ein vollständiges Beispiel:

Datenbankeinstellungen:


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',
  },
}
Wenn Sie folgende Effekte erzielen möchten:

Das Lesen und Schreiben des Modells, dessen app_label auth ist, wird in auth_db abgeschlossen, der Rest des Modellschreibens wird in der Primärdatenbank abgeschlossen und das Lesen wird zufällig in Replikat1 und Replikat2 abgeschlossen.

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
Auf diese Weise werden das Lesen und Schreiben des Modells, dessen app_label auth ist, in auth_db abgeschlossen und Assoziationen zugelassen . Die Migration erfolgt nur in der auth_db-Datenbank.

Der Rest:


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
Auf diese Weise erfolgt das Lesen zufällig in Replikat1 und Replikat2, und das Schreiben verwendet Primär.

Stellen Sie es schließlich in den Einstellungen ein:


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

Beim Durchführen eines Migrationsvorgangs:


$ ./manage.py migrate
$ ./manage.py migrate --database=users
Der Migrationsvorgang wird standardmäßig auf der Standarddatenbank ausgeführt. Um auf anderen Datenbanken zu arbeiten, können Sie verwenden Option --database, gefolgt vom Alias ​​der Datenbank.

Entsprechend verfügen die Befehle dbshell, dumpdata und loaddata alle über die Option --database.

Sie können die Route auch manuell auswählen:

Abfrage:


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


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


>>> p = Person(name='Fred')
>>> p.save(using='first') # (statement 1)
>>> p.save(using='second') # (statement 2)
Der obige Code führt zu Problemen, wenn p zum ersten Mal in der ersten Datenbank gespeichert wird. Es wird standardmäßig einen Primärschlüssel generieren, sodass p beim Speichern in der zweiten Datenbank bereits über einen Primärschlüssel verfügt. Dieser Primärschlüssel verursacht keine Probleme, wenn er nicht verwendet wird. Wenn er jedoch zuvor verwendet wurde, werden die Originaldaten überschrieben .

Es gibt zwei Lösungen:

1. Löschen Sie den Primärschlüssel vor dem Speichern:


>>> 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. Verwenden Sie force_insert


>>> p = Person(name='Fred')
>>> p.save(using='first')
>>> p.save(using='second', force_insert=True)
, um zu löschen:

Aus welcher Datenbank das Objekt stammt und wo es gelöscht werden soll


>>> u = User.objects.using('legacy_users').get(username='fred')
>>> u.delete() # will delete from the `legacy_users` database
Wenn Sie ein Objekt aus der Legacy_users-Datenbank in die new_users-Datenbank übertragen möchten:


Das obige ist der detaillierte Inhalt vonEinführung in die Verwendung mehrerer Datenbankmethoden durch Django. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn