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