Фикстуры
Что такое фикстура?
Фикстура — это набор файлов, содержащих сериализованное содержимое базы данных. Каждая фикстура имеет уникальное имя, а файлы, составляющие фикстуру, могут быть распределены по нескольким каталогам, в нескольких приложениях.
Как создать фикстуру?
Фикстуры могут быть сгенерированы с помощью manage.py dumpdata. Также можно создать пользовательские фикстуры, напрямую используя инструменты сериализации, или даже написав их вручную.
Как использовать фикстуру?
Фикстуры могут использоваться для предварительной заполнения базы данных данными для тестов:
class MyTestCase(TestCase):
fixtures = ["fixture-label"]
или для предоставления некоторых начальных данных с помощью команды loaddata:
django-admin loaddata <fixture label>
Где Django ищет фикстуры?
Django будет искать фикстуры в этих местах:
- В каталоге
fixturesкаждого установленного приложения - В любом каталоге, указанном в настройке
FIXTURE_DIRS - В указанном по буквам пути к фикстуре
Django загрузит все найденные им фикстуры в этих местах, соответствующие указанным именам фикстур. Если у именованной фикстуры есть расширение файла, будут загружены только фикстуры с этим типом. Например:
django-admin loaddata mydata.json
будут загружены только JSON-фикстуры с именем mydata. Расширение фикстуры должно соответствовать зарегистрированному имени сериализатора (например, 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 по 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.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.1/topics/db/fixtures/