Приспособления¶
Что такое крепление?¶
Приспособление fixture - это набор файлов, которые содержат сериализованное содержимое базы данных. Каждое приспособление имеет уникальное имя, а файлы, составляющие приспособление, могут быть распределены по нескольким каталогам в нескольких приложениях.
Как изготовить приспособление?¶
Фиксики могут быть сгенерированы с помощью manage.py dumpdata
. Также можно генерировать пользовательские фикстуры непосредственно с помощью serialization tools или даже вписывая их вручную.
Как использовать приспособление?¶
Фиксики могут использоваться для предварительного заполнения базы данных данными для tests:
class MyTestCase(TestCase):
fixtures = ["fixture-label"]
или предоставить некоторые initial data с помощью команды loaddata
:
django-admin loaddata <fixture label>
Где Django ищет крепления?¶
Django будет искать фиксы в этих местах:
- В каталоге
fixtures
каждого установленного приложения - В любом каталоге, указанном в настройках
FIXTURE_DIRS
- В буквальном пути, названном приспособлением
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
.