Приспособления

Что такое крепление?

Приспособление fixture - это набор файлов, которые содержат сериализованное содержимое базы данных. Каждое приспособление имеет уникальное имя, а файлы, составляющие приспособление, могут быть распределены по нескольким каталогам в нескольких приложениях.

Как изготовить приспособление?

Фиксики могут быть сгенерированы с помощью manage.py dumpdata. Также можно генерировать пользовательские фикстуры непосредственно с помощью serialization tools или даже вписывая их вручную.

Как использовать приспособление?

Фиксики могут использоваться для предварительного заполнения базы данных данными для tests:

class MyTestCase(TestCase):
    fixtures = ["fixture-label"]

или предоставить некоторые initial data с помощью команды loaddata:

django-admin loaddata <fixture label>

Где Django ищет крепления?

Django будет искать фиксы в этих местах:

  1. В каталоге fixtures каждого установленного приложения
  2. В любом каталоге, указанном в настройках FIXTURE_DIRS
  3. В буквальном пути, названном приспособлением

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

django-admin loaddata mydata.json

будет загружать только JSON-фиксаторы с именем mydata. Расширение приспособления должно соответствовать зарегистрированному имени serializer (например, json или xml).

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

django-admin loaddata mydata

будет искать любое приспособление любого типа с именем mydata. Если каталог приспособлений содержит mydata.json, то это приспособление будет загружено как JSON-приспособление.

Именованные приспособления могут включать компоненты каталогов. Эти каталоги будут включены в путь поиска. Например:

django-admin loaddata foo/bar/mydata.json

будет искать <app_label>/fixtures/foo/bar/mydata.json для каждого установленного приложения, <dirname>/foo/bar/mydata.json для каждого каталога в FIXTURE_DIRS и литеральный путь foo/bar/mydata.json.

Порядок загрузки приспособлений

В одном вызове можно указать несколько приспособлений. Например:

django-admin loaddata mammals birds insects

или в классе тестовых примеров:

class AnimalTestCase(TestCase):
    fixtures = ["mammals", "birds", "insects"]

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

В этих примерах сначала будут загружены все приспособления с именем mammals из всех приложений (в том порядке, в котором приложения определены в INSTALLED_APPS). Затем будут загружены все светильники birds, а затем все светильники insects.

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

Каким образом приспособления сохраняются в базе данных?

Когда файлы приспособлений обрабатываются, данные сохраняются в базе данных как есть. Методы save(), определенные моделью, не вызываются, а любые сигналы pre_save или post_save будут вызываться с raw=True, поскольку экземпляр содержит только атрибуты, локальные для модели. Вы можете, например, захотеть отключить обработчики, обращающиеся к связанным полям, которые не присутствуют во время загрузки приспособления и в противном случае вызовут исключение:

from django.db.models.signals import post_save
from .models import MyModel


def my_handler(**kwargs):
    # disable the handler during fixture loading
    if kwargs["raw"]:
        return
    ...


post_save.connect(my_handler, sender=MyModel)

Вы также можете написать декоратор для инкапсуляции этой логики:

from functools import wraps


def disable_for_loaddata(signal_handler):
    """
    Decorator that turns off signal handlers when loading fixture data.
    """

    @wraps(signal_handler)
    def wrapper(*args, **kwargs):
        if kwargs["raw"]:
            return
        signal_handler(*args, **kwargs)

    return wrapper


@disable_for_loaddata
def my_handler(**kwargs):
    ...

Только учтите, что эта логика будет отключать сигналы при любой десериализации фикстуры, а не только при loaddata.

Сжатые приспособления

Крепления могут быть сжаты в формате zip, gz, bz2, lzma или xz. Например:

django-admin loaddata mydata.json

будет искать любой из mydata.json, mydata.json.zip, mydata.json.gz, mydata.json.bz2, mydata.json.lzma или mydata.json.xz. Используется первый файл, содержащийся в сжатом архиве.

Обратите внимание, что если обнаружены два приспособления с одинаковым именем, но разным типом приспособления (например, если mydata.json и mydata.xml.gz были найдены в одном каталоге приспособлений), установка приспособления будет прервана, а все данные, установленные при вызове loaddata, будут удалены из базы данных.

MySQL с MyISAM и креплениями

Механизм хранения MyISAM в MySQL не поддерживает транзакции или ограничения, поэтому если вы используете MyISAM, вы не получите проверку данных фиксации или откат при обнаружении нескольких файлов транзакций.

Приспособления, специфичные для базы данных

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

Например, если в настройке DATABASES определена база данных users, назовите приспособление mydata.users.json или mydata.users.json.gz, и оно будет загружаться только тогда, когда вы укажете, что хотите загрузить данные в базу users.

Вернуться на верх