Несколько баз данных

В этом руководстве описывается поддержка Django нескольких баз данных. Большая часть документации Django предполагает, что вы работаете с одной базой данных. Если вам нужно работать с несколькими базами данных, потребуется выполнить некоторые дополнительные настройки.

Смотрите также

См. Раздел Поддержка нескольких баз данных для получения информации о тестировании с несколькими базами данных.

Определение баз данных

Первое, что нужно сделать, если вы хотите использовать более одной базы данных с Django, - это объяснить ей, какие серверы баз данных использовать. Это делается при настройке DATABASES . Эта настройка сопоставляет псевдонимы базы данных, которые являются способом ссылки на определенные базы данных в коде Django, в словарь настроек для соответствующего соединения. Настройки внутреннего словаря подробно описаны в документации для DATABASES .

Псевдоним базы данных можно выбрать произвольно. Однако у псевдонима default есть особое значение. Django использует базу данных с псевдонимом, default когда не выбрана другая база данных.

Следующий пример представляет собой отрывок из settings.py определения двух баз данных, базы данных PostgreSQL по умолчанию и именованной базы данных MySQL users :

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

Если концепция базы данных по умолчанию не имеет смысла в контексте вашего проекта, вы всегда должны пытаться указать, какую базу данных использовать. Django требует, чтобы была определена именованная база данных default , но словарь параметров можно оставить пустым, если он не используется. Для этого вы должны настроить DATABASE_ROUTERS все шаблоны ваших приложений, включая шаблоны приложений contrib или сторонних приложений, которые вы используете, чтобы никакие запросы не направлялись в базу данных по умолчанию. Следующий пример представляет собой отрывок из settings.py определения двух конкретных баз данных, в котором запись default намеренно оставлена ​​пустой:

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': '[email protected]'
    }
}

Если вы попытаетесь получить доступ к базе данных, которая не определена в настройках DATABASES , Django выдает исключение django.db.utils.ConnectionDoesNotExist .

Синхронизация баз данных

Команда управления одновременно migrate работает только с одной базой данных. По умолчанию он работает с базой данных default , но, заполнив эту опцию --database , вы можете попросить его синхронизировать другую базу данных. Итак, чтобы синхронизировать все модели из всех баз данных в первом примере выше, вам нужно будет запустить:

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

Если вы не хотите, чтобы каждое приложение синхронизировалось с определенной базой данных, вы можете определить маршрутизатор базы данных, реализующий политику ограничения доступности определенных моделей.

Если, как во втором примере выше, вы оставили базу данных пустой default , вы должны указывать имя базы данных при каждом запуске migrate . Без него будет выдана ошибка. Для второго примера:

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

Использование других команд управления

Большинство других команд, которые django-admin взаимодействуют с базой данных, работают так же, как migrate , то есть они всегда работают только с одной базой данных за раз, в зависимости от настройки --database для знать, какую базу данных использовать.

Исключением из этого правила является заказ makemigrations . Он проверяет историю миграций в базе данных, чтобы обнаружить возможные проблемы с существующими файлами миграции (например, после ручного выпуска) перед созданием новых миграций. По умолчанию, он контролирует только базу данных default , но он консультируется метод allow_migrate() из маршрутизаторов при условии , имеется.

Автоматическая маршрутизация базы данных

Самый простой способ использовать несколько баз данных - определить план маршрутизации базы данных. План маршрутизации по умолчанию гарантирует, что объекты остаются «прикрепленными» к своей исходной базе данных (т. Е. Объект, полученный из базы данных foo , также будет сохранен в той же базе данных). План маршрутизации по умолчанию гарантирует, что без какой-либо конкретной индикации базы данных все запросы будут направляться в базу данных default .

Вам не нужно ничего делать, чтобы активировать план маршрутизации по умолчанию, он изначально активируется для любого проекта Django. Однако, если вы намереваетесь реализовать более сложное поведение распределения между базами данных, у вас есть возможность определить и установить свои собственные маршрутизаторы базы данных.

Маршрутизаторы баз данных

База данных router ( Router ) - это класс, предоставляющий до четырех методов:

db_for_read( модель , ** подсказки )

Предложите, какую базу данных использовать для операций чтения для объектов типа model .

Если операция с базой данных может предоставить дополнительную информацию, которая может помочь в выборе базы данных, она будет содержаться в словаре hints . Ниже вы найдете более подробную информацию о возможном содержании hints .

Возвращает, None если предложений нет.

db_for_write( модель , ** подсказки )

Предлагает базу данных для использования для операций записи для объектов типа Model .

Если операция с базой данных может предоставить дополнительную информацию, которая может помочь в выборе базы данных, она будет содержаться в словаре hints . Ниже вы найдете более подробную информацию о возможном содержании hints .

Возвращает, None если предложений нет.

allow_relation( obj1 , obj2 , ** подсказки )

Возвращает True , разрешена ли связь между obj1 и obj2 , запрещена False ли связь или None маршрутизатор не получил уведомления. Это чисто операция проверки, которая используется операциями внешнего ключа и отношений «многие ко многим», чтобы определить, следует ли разрешать отношения между двумя объектами.

Если ни один маршрутизатор не имеет мнения (т.е. все маршрутизаторы возвращаются None ), принимаются только отношения в пределах одной базы данных.

allow_migrate( db , app_label , model_name = None , ** подсказки )

Определяет, разрешено ли выполнение операции миграции для базы данных с псевдонимом db . Возвращает True , следует ли применять операцию, False если нет, или None если маршрутизатор не получил уведомления.

Позиционный параметр app_label - это метка переносимого приложения.

model_name устанавливается большинством операций миграции на значение model._meta.model_name (версия __name__ модели в нижнем регистре ) модели, которую необходимо перенести. Его значение предназначено None для операций, RunPython и RunSQL если они не предоставляют ему указания ( hints ).

hints используется некоторыми операциями для передачи дополнительной информации маршрутизатору.

Когда model_name установлено, hints обычно в ключе содержится класс модели 'model' . Обратите внимание, что это может быть историческая модель и, следовательно, не иметь каких-либо настраиваемых атрибутов, методов или обработчиков. Можно только положиться _meta .

Этот метод также можно использовать для определения доступности модели в конкретной базе данных.

makemigrations всегда создает миграции для изменений модели, но если какой-либо allow_migrate() возврат False для операций миграции model_name будет игнорироваться при запуске migrate для db . Изменение поведения allow_migrate() для моделей, которые уже имеют миграции, может привести к повреждению внешних ключей, лишним таблицам или отсутствующим таблицам. При makemigrations проверке истории миграции он игнорирует базы данных, для которых ни одно приложение не допускает миграции.

Маршрутизатору не обязательно реализовывать все эти методы, он может опустить один или несколько из них. Если какой-либо из методов отсутствует, Django пропускает этот маршрутизатор при выполнении соответствующей проверки.

Показания ( hints )

Индикация, полученная маршрутизатором базы данных в словаре, hints может использоваться, чтобы решить, какая база данных должна получить данный запрос.

В настоящее время предоставляется единственная индикация - instance экземпляр объекта, связанный с текущей операцией чтения или записи. Это может быть зарегистрированный экземпляр или экземпляр, который будет добавлен в отношении «многие ко многим». В некоторых случаях индикация экземпляра отсутствует. Маршрутизатор проверяет наличие индикации экземпляра и сам определяет, следует ли использовать этот экземпляр для изменения поведения маршрутизации.

Использование роутеров

Маршрутизаторы баз данных устанавливаются по настройке DATABASE_ROUTERS . Этот параметр определяет список имен классов, каждое из которых определяет маршрутизатор, который будет использоваться главным маршрутизатором ( django.db.router ).

Главный маршрутизатор используется операциями с базами данных Django для определения используемых баз данных. Всякий раз, когда запросу необходимо знать, какую базу данных использовать, он вызывает главный маршрутизатор, указывая шаблон, а также индекс (если он доступен). Затем Django пробует каждый маршрутизатор по очереди, пока не будет найдено предложение базы данных. Если предложение не найдено, он пытается использовать свойство instance._state.db экземпляра индекса. Если индекс не был указан или если он instance._state.db содержит None , главный маршрутизатор указывает базу данных default .

Пример

Только в качестве примера!

Этот пример предназначен для демонстрации того, как можно использовать инфраструктуру маршрутизации для изменения использования базы данных. Он намеренно игнорирует некоторые сложные вопросы, чтобы продемонстрировать, как можно использовать маршрутизаторы.

Этот пример не будет работать, если какая-либо из моделей myapp содержит отношения с моделями, хранящимися в другом месте, кроме базы данных other . Отношения между базами данных вызывают проблемы ссылочной целостности, с которыми Django в настоящее время не справляется.

Представленная здесь первичная / репликационная конфигурация (обозначенная некоторыми базами данных как ведущая / ведомая) также является предвзятой, поскольку она не предлагает никакого решения для управления задержками репликации (т.е. несогласованность запросов из-за времени необходимо для распространения записи на реплики). Он также не учитывает взаимодействие транзакций со стратегией использования базы данных.

Но что это означает на практике? Рассмотрим другой пример конфигурации. Он будет содержать несколько баз данных: одна для приложения, auth а все другие приложения будут использовать конфигурацию первичной / реплики с двумя репликами только для чтения. Вот настройки, определяющие эти базы данных:

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

Теперь нам нужно управлять маршрутизацией. Во-первых, нам нужен маршрутизатор, который может отправлять запросы для приложений auth и contenttypes в auth_db (модели auth связаны ContentType , поэтому они должны храниться в одной базе данных)

class AuthRouter:
    """
    A router to control all database operations on models in the
    auth and contenttypes applications.
    """
    route_app_labels = {'auth', 'contenttypes'}

    def db_for_read(self, model, **hints):
        """
        Attempts to read auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth or contenttypes apps is
        involved.
        """
        if (
            obj1._meta.app_label in self.route_app_labels or
            obj2._meta.app_label in self.route_app_labels
        ):
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth and contenttypes apps only appear in the
        'auth_db' database.
        """
        if app_label in self.route_app_labels:
            return db == 'auth_db'
        return None

И мы также хотим, чтобы маршрутизатор для всех других приложений отправлял свои запросы в конфигурацию первичной / реплики, при этом случайным образом выбирая реплику для чтения:

import random

class PrimaryReplicaRouter:
    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_set = {'primary', 'replica1', 'replica2'}
        if obj1._state.db in db_set and obj2._state.db in db_set:
            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

Наконец, мы добавляем в файл настроек следующий код (заменяя path.to. фактический путь Python к модулям, в которых определены маршрутизаторы):

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

Порядок, в котором обрабатываются маршрутизаторы, имеет значение. Маршрутизаторы запрашиваются в том порядке, в котором они указаны в настройке DATABASE_ROUTERS . В этом примере AuthRouter обрабатывается раньше PrimaryReplicaRouter , и поэтому решения о моделях auth принимаются до любых других решений. Если параметр DATABASE_ROUTERS содержит два маршрутизатора в обратном порядке, PrimaryReplicaRouter.allow_migrate() сначала будет обработан. Универсальный характер реализации PrimaryReplicaRouter означает, что все модели будут доступны во всех базах данных.

После установки этой установки давайте запустим несколько фрагментов Django:

>>> # This retrieval will be performed on the 'auth_db' database
>>> fred = User.objects.get(username='fred')
>>> fred.first_name = 'Frederick'

>>> # This save will also be directed to 'auth_db'
>>> fred.save()

>>> # These retrieval will be randomly allocated to a replica database
>>> dna = Person.objects.get(name='Douglas Adams')

>>> # A new object has no database allocation when created
>>> mh = Book(title='Mostly Harmless')

>>> # This assignment will consult the router, and set mh onto
>>> # the same database as the author object
>>> mh.author = dna

>>> # This save will force the 'mh' instance onto the primary database...
>>> mh.save()

>>> # ... but if we re-retrieve the object, it will come back on a replica
>>> mh = Book.objects.get(title='Mostly Harmless')

В этом примере определен маршрутизатор для обработки взаимодействия с моделями приложений auth и другие маршрутизаторы для обработки взаимодействия со всеми другими приложениями. Если вы оставили базу данных пустой default и не хотели настраивать «универсальный» маршрутизатор базы данных для обработки всех приложений, не указанных явно, маршрутизаторы должны обработать имена всех приложений INSTALLED_APPS перед этим. выполнить миграцию. См. « Поведение добавленных приложений» для получения дополнительной информации о добавленных приложениях, которые должны находиться вместе в одной базе данных.

Выбор базы данных вручную

Django также предлагает API для полного контроля над использованием баз данных в вашем коде. Назначение базы данных вручную имеет приоритет над назначением от маршрутизатора.

Выбор базы данных для вручнуюQuerySet

Вы можете выбрать базу данных из одной QuerySet в любое время в «цепочке» из QuerySet . Вызов using() на QuerySet получить другую , QuerySet используя указанную базу данных.

using() принимает только один параметр: псевдоним базы данных для получения выполняемого запроса. Например :

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

Используйте именованный параметр using из Model.save() указать , в котором база данных данные должны быть сохранены.

Например, чтобы сохранить объект в базе данных legacy_users , вы должны написать это:

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

Если оставить using поле пустым , метод save() сохраняется в базе данных по умолчанию, назначенной маршрутизаторами.

Перемещение объекта между базами данных

Если вы сохранили экземпляр в базе данных, может возникнуть соблазн использовать save(using=...) в качестве уловки для копирования экземпляра в новую базу данных. Однако если не принять необходимые меры предосторожности, это может привести к непредвиденным последствиям.

Рассмотрим следующий пример:

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

В инструкции 1 новый объект Person регистрируется в базе данных first . На данный момент p еще нет первичного ключа, поэтому Django генерирует оператор SQL INSERT . Таким образом создается первичный ключ, и Django назначает этот первичный ключ p .

Когда регистрация выполняется в операторе 2, p уже получено значение первичного ключа, и Django будет использовать этот первичный ключ в новой базе данных. Если это значение первичного ключа еще не используется в базе данных second , проблем не возникнет, объект будет фактически скопирован в новую базу данных.

Однако, если первичный ключ p уже используется в базе данных second , существующий объект в базе данных second будет перезаписан при сохранении p .

Вы можете предотвратить это двумя способами. Во-первых, вы можете очистить первичный ключ экземпляра. Если у объекта нет первичного ключа, Django рассматривает его как новый объект, предотвращая потерю данных в базе данных second :

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

Вторая возможность заключается в использовании опции force_insert из , save() чтобы убедиться , что Django производит оператор SQL INSERT :

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

Это гарантирует, что указанный человек будет Fred иметь один и тот же первичный ключ в обеих базах данных. Если этот первичный ключ уже используется при попытке сохранить в базе данных second , будет сгенерирована ошибка.

Выбор базы данных для удаления

По умолчанию вызов для удаления существующего объекта будет выполнен в той же базе данных, которая использовалась для извлечения объекта раньше:

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

Чтобы указать базу данных, в которой будет удалена модель, передайте using в метод именованный параметр Model.delete() . Этот параметр играет ту же роль, что и тот же параметр с save() .

Например, если вы переносите пользователя из базы данных legacy_users в базу данных new_users , вот команды, которые вы можете использовать:

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

Использование менеджеров с несколькими базами данных

Используйте метод db_manager() менеджеров, чтобы предоставить менеджерам доступ к базе данных, отличной от базы данных по умолчанию.

Например, предположим, что у вас есть метод настраиваемого обработчика, действующего в базе данных User.objects.create_user() . Поскольку create_user() это метод обработчика, а не метод QuerySet , его невозможно записать User.objects.using('new_users').create_user() (метод create_user() доступен только для User.objects обработчика, а не для объектов, QuerySet производных от обработчика). Решение состоит в db_manager() следующем:

User.objects.db_manager('new_users').create_user(...)

db_manager() возвращает копию менеджера, связанного с указанной вами базой данных.

Использование get_queryset() с несколькими базами данных

Если вы перегружаете get_queryset() свой обработчик, не забудьте либо вызвать родительский метод (using super() ), либо соответствующим образом обработать атрибут _db обработчика (строку, содержащую имя используемой базы данных).

Например, если вы хотите вернуть QuerySet собственный класс из метода get_queryset , вы можете сделать это:

class MyManager(models.Manager):
    def get_queryset(self):
        qs = CustomQuerySet(self.model)
        if self._db is not None:
            qs = qs.using(self._db)
        return qs

Отображение нескольких баз данных в интерфейсе администрирования

Интерфейс администратора Django не содержит явной поддержки нескольких баз данных. Если вы хотите предоставить интерфейс администрирования для модели в базе данных, отличной от той, которая указана в вашей цепочке маршрутизации, вам нужно будет написать ModelAdmin пользовательские классы , которые побудят администрацию использовать базу данных. конкретные данные для содержания.

У объектов ModelAdmin есть пять методов, требующих адаптации для поддержки нескольких баз данных:

class MultiDBModelAdmin(admin.ModelAdmin):
    # A handy constant for the name of the alternate database.
    using = 'other'

    def save_model(self, request, obj, form, change):
        # Tell Django to save objects to the 'other' database.
        obj.save(using=self.using)

    def delete_model(self, request, obj):
        # Tell Django to delete objects from the 'other' database
        obj.delete(using=self.using)

    def get_queryset(self, request):
        # Tell Django to look for objects on the 'other' database.
        return super().get_queryset(request).using(self.using)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # Tell Django to populate ForeignKey widgets using a query
        # on the 'other' database.
        return super().formfield_for_foreignkey(db_field, request, using=self.using, **kwargs)

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        # Tell Django to populate ManyToMany widgets using a query
        # on the 'other' database.
        return super().formfield_for_manytomany(db_field, request, using=self.using, **kwargs)

В приведенном выше примере реализуется стратегия, основанная на нескольких базах данных, где все объекты данного типа хранятся в конкретной базе данных (например, все объекты User находятся в базе данных other ). Если вы используете несколько баз данных более сложно, ваш класс ModelAdmin должен будет отразить эту стратегию.

InlineModelAdmin Аналогичным образом можно управлять объектами . Для них требуются три специальных метода:

class MultiDBTabularInline(admin.TabularInline):
    using = 'other'

    def get_queryset(self, request):
        # Tell Django to look for inline objects on the 'other' database.
        return super().get_queryset(request).using(self.using)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # Tell Django to populate ForeignKey widgets using a query
        # on the 'other' database.
        return super().formfield_for_foreignkey(db_field, request, using=self.using, **kwargs)

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        # Tell Django to populate ManyToMany widgets using a query
        # on the 'other' database.
        return super().formfield_for_manytomany(db_field, request, using=self.using, **kwargs)

После написания определений административных классов моделей их можно зарегистрировать в любом экземпляре Admin :

from django.contrib import admin

# Specialize the multi-db admin objects for use with specific models.
class BookInline(MultiDBTabularInline):
    model = Book

class PublisherAdmin(MultiDBModelAdmin):
    inlines = [BookInline]

admin.site.register(Author, MultiDBModelAdmin)
admin.site.register(Publisher, PublisherAdmin)

othersite = admin.AdminSite('othersite')
othersite.register(Publisher, MultiDBModelAdmin)

В этом примере настраиваются два сайта администрирования. На первом сайте выставлены объекты Author и Publisher ; объекты Publisher имеют подчиненную табличную форму, в которой отображаются книги, опубликованные этим издателем. На втором сайте представлены только редакторы без подчиненной формы.

Использование курсоров напрямую с несколькими базами данных

Если вы используете несколько баз данных, вы можете использовать их django.db.connections для получения соединения (и курсора) для конкретной базы данных. django.db.connections - это объект типа словаря, позволяющий получить конкретное соединение с помощью его псевдонима:

from django.db import connections
with connections['my_db_alias'].cursor() as cursor:
    ...

Ограничения нескольких баз данных

Взаимосвязи между базами данных

Django в настоящее время не поддерживает внешние ключи или отношения «многие ко многим» между разными базами данных. Если вы использовали маршрутизатор для распределения шаблонов по разным базам данных, любой внешний ключ или отношения «многие ко многим», определенные этими шаблонами, должны быть внутренними по отношению к одной базе данных.

Причина - ссылочная целостность. Чтобы поддерживать связь между двумя объектами, Django необходимо знать, что первичный ключ связанного объекта действителен. Если первичный ключ хранится в другой базе данных, невозможно легко оценить действительность первичного ключа.

Если вы используете Postgres, Oracle или MySQL с InnoDB, эта гарантия целостности предоставляется на уровне базы данных, поскольку ключевые ограничения на уровне базы данных предотвращают создание отношений, которые не могут быть проверены.

Однако, если вы используете SQLite или MySQL с таблицами MyISAM, ссылочная целостность отсутствует; следовательно, между базами данных можно создавать «смоделированные» внешние ключи. Однако эта конфигурация официально не поддерживается Django.

Поведение добавленных приложений

Несколько добавленных приложений содержат шаблоны, а некоторые приложения имеют зависимости. Поскольку перекрестные отношения между базами данных невозможны, это приводит к некоторым ограничениям на то, как эти модели могут совместно использоваться разными базами данных:

  • Шаблоны contenttypes.ContentType , sessions.Session и sites.Site могут быть независимо друг от друга хранится в любой базе данных, до тех пор , как используется подходящий маршрутизатор.
  • Модели auth ( User , Group и Permission ) связаны друг с другом и с ContentType , поэтому они должны храниться в той же базе данных, что и ContentType .
  • admin зависит от auth , поэтому его модели должны находиться в той же базе данных, что и auth .
  • flatpages и redirects зависят от sites , поэтому их модели должны находиться в той же базе данных, что и sites .

Кроме того, некоторые объекты автоматически создаются сразу после migrate создания таблицы для хранения их в базе данных:

  • один Site по умолчанию,
  • по одному ContentType на каждую модель (в том числе те, которые не хранятся в базе данных),
  • их Permission для каждой модели (включая те, которые не хранятся в базе данных).

Для обычных конфигураций с несколькими базами данных нецелесообразно иметь эти объекты более чем в одной базе данных. Эти общие конфигурации включают в себя конфигурации главный-подчиненный и подключение к внешним базам данных. Поэтому рекомендуется написать маршрутизатор базы данных, позволяющий синхронизировать эти три модели с единой базой данных. Используйте тот же подход для других приложений или сторонних приложений, таблицы которых не обязательно должны находиться в нескольких базах данных.

Предупреждение

Если вы синхронизируете типы контента в нескольких базах данных, имейте в виду, что их первичные ключи могут отличаться от базы данных к базе данных. Это может привести к повреждению или потере данных.

Copyright ©2021 All rights reserved