Spec-Zone.ru › Django 4.0

Базы данных

В этом руководстве описывается поддержка Django для взаимодействия с несколькими базами данных. Большая часть остальной документации 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'
    }
}

Если понятие базы данных по умолчанию default не имеет смысла в контексте вашего проекта, вам нужно быть внимательным, чтобы всегда указывать используемую базу данных. 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': 'veryPriv@ate'
    }
}

Если вы попытаетесь получить доступ к базе данных, которую вы не определили в настройке DATABASES, Django поднимет исключение django.utils.connection.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. Однако, если вы хотите реализовать более интересные поведенческие характеристики распределения баз данных, вы можете определить и установить свои собственные маршрутизаторы баз данных.

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

Маршрутизатор баз данных — это класс, предоставляющий до четырёх методов:

db_for_read(model, **hints)

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

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

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

db_for_write(model, **hints)

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

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

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

allow_relation(obj1, obj2, **hints)

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

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

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

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

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

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

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

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

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

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

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

Подсказки

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

В настоящее время единственной предоставленной подсказкой является 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 перед миграцией. См. Поведение приложений contrib для получения информации о приложениях contrib, которые должны быть вместе в одной базе данных.

Ручное выбор базы данных

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(). Этот аргумент работает так же, как и ключевой аргумент using к 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() в своём менеджере, убедитесь, что вы либо вызываете этот метод у родительского класса (используя 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

Интерфейс администрирования 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 имеют табличный вложенный элемент, показывающий книги, опубликованные этим издателем. Второй сайт отображает только издателей, без вложенных элементов.

END_OF_DOCUMENT_MARKER

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

Если вы используете более одной базы данных, вы можете использовать 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.

Поведение приложений contrib

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

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

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

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

В распространенных настройках с несколькими базами данных нецелесообразно хранить эти объекты в более чем одной базе данных. К распространенным настройкам относятся первичная/реплицируемая и подключение к внешним базам данных. Поэтому рекомендуется написать роутер базы данных маршрутизатор базы данных, который позволит синхронизировать эти три модели только с одной базой данных. Применяйте тот же подход к приложениям contrib и сторонних разработчиков, которым не нужны их таблицы в нескольких базах данных.

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

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

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.0/topics/db/multi-db/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API