固定数据 是包含数据库序列化内容的文件集合。每个固定数据都有一个独有的名称,组成固定数据的文件可以分布在多个应用程序的多个目录中。
See also
固定装置可以通过 manage.py dumpdata 生成。还可以通过直接使用 序列化工具 或甚至手工编写来生成自定义固定装置。
Fixture 可以用于在数据库中预填充数据以用于 测试:
class MyTestCase(TestCase):
fixtures = ["fixture-label"]
django-admin loaddata <fixture label>
Django 会在以下位置搜索固定装置:
在每个安装的应用程序的 fixtures 目录中
在 FIXTURE_DIRS 设置中列出的任何目录中。
在由固定数据命名的文字路径中
Django 会加载在这些位置找到的与提供的固定装置名称匹配的所有固定装置。如果命名的固定装置有文件扩展名,那么只会加载该类型的固定装置。例如:
django-admin loaddata mydata.json
将只加载名为 mydata 的 JSON 固定数据。固定数据扩展必须与 序列化器 的注册名称相对应(例如,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,在 FIXTURE_DIRS 中的每个目录中搜索 <dirname>/foo/bar/mydata.json,以及字面路径 foo/bar/mydata.json。
可以在同一次调用中指定多个固定装置。例如:
django-admin loaddata mammals birds insects
或者在测试用例类中:
class AnimalTestCase(TestCase):
fixtures = ["mammals", "birds", "insects"]
固定装置加载的顺序遵循它们在列表中列出的顺序,无论是在使用管理命令时还是在测试用例类中如上所示。
在这些示例中,首先将加载所有应用程序中命名为 mammals 的固定装置(按照 INSTALLED_APPS 中应用程序的定义顺序)。随后,将加载所有的 birds 固定装置,然后是所有的 insects 固定装置。
请注意,如果数据库后端支持行级约束,这些约束将在事务结束时进行检查。如果跨固定装置存在关联关系,并且数据库配置不支持延迟约束检查,可能会导致加载错误(请参考 MySQL 文档以获取示例)。
When fixture files are processed, the data is saved to the database as is.
Model defined save() methods are not called, and
any pre_save,
post_save, or
m2m_changed signals will be called with
raw=True since the instance only contains attributes that are local to the
model. You may, for example, want to disable handlers that access
related fields that aren't present during fixture loading and would otherwise
raise an exception:
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 过程中。
The raw argument was added to m2m_changed signals.
固定装置可以以 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 调用中安装的任何数据都将从数据库中删除。
使用 MyISAM 的 MySQL 与固定数据
MySQL 的 MyISAM 存储引擎不支持事务或约束,所以如果你使用 MyISAM,你不会得到固定数据的数据验证,如果发现多个事务文件,也不会有回滚。
如果你在一个多数据库配置中,你可能会有想加载到一个数据库,但不加载到另一个数据库的固定数据。在这种情况下,你可以在固定数据的名称中添加一个数据库标识符。
例如,如果你的 DATABASES 设置中定义了一个名为 users 的数据库,那么将固定装置命名为 mydata.users.json 或 mydata.users.json.gz,那么这个固定装置只会在你指定要加载数据到 users 数据库时才会被加载。
8月 05, 2026