Фикстуры
Что такое фикстура?
Фикстура — это набор файлов, содержащих сериализованное содержимое базы данных. Каждая фикстура имеет уникальное имя, а файлы, составляющие фикстуру, могут быть распределены по нескольким каталогам и приложениям.
Как создать фикстуру?
Фикстуры могут быть сгенерированы с помощью 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 для примера).
Как фикстуры сохраняются в базе данных?
При обработке файлов фикстур данные сохраняются в базе данных как есть. Определенные в модели методы 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.0/topics/db/fixtures/