辅助工具¶
固定数据 是包含数据库序列化内容的文件集合。每个固定数据都有一个独有的名称,组成固定数据的文件可以分布在多个应用程序的多个目录中。
See also
How to produce a fixture¶
固定装置可以通过 manage.py dumpdata
生成。还可以通过直接使用 序列化工具 或甚至手工编写来生成自定义固定装置。
How to use a fixture¶
Fixtures can be used to pre-populate the database with data for tests:
class MyTestCase(TestCase):
fixtures = ["fixture-label"]
django-admin loaddata <fixture label>
How fixtures are discovered¶
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 文档以获取示例)。
How fixtures are saved to the database¶
当固定数据文件被处理后,数据会被原样保存到数据库中。模型定义的 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
调用中安装的任何数据都将从数据库中删除。
使用 MyISAM 的 MySQL 与固定数据
MySQL 的 MyISAM 存储引擎不支持事务或约束,所以如果你使用 MyISAM,你不会得到固定数据的数据验证,如果发现多个事务文件,也不会有回滚。
特定数据库的固定数据¶
如果你在一个多数据库配置中,你可能会有想加载到一个数据库,但不加载到另一个数据库的固定数据。在这种情况下,你可以在固定数据的名称中添加一个数据库标识符。
例如,如果你的 DATABASES
设置中定义了一个名为 users
的数据库,那么将固定装置命名为 mydata.users.json
或 mydata.users.json.gz
,那么这个固定装置只会在你指定要加载数据到 users
数据库时才会被加载。