{"title":"辅助工具","version":"6.1","locale":"zh-hans","docname":"topics/db/fixtures","url":"/zh-hans/6.1/topics/db/fixtures/","canonical":"https://djangodocs.dev/zh-hans/6.1/topics/db/fixtures/","summary":"固定数据是包含数据库序列化内容的文件集合。每个固定数据都有一个独有的名称，组成固定数据的文件可以分布在多个应用程序的多个目录中。","html":"<span id=\"fixtures-explanation\"></span><h1>辅助工具<a class=\"heading-anchor\" href=\"#fixtures\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p><em>固定数据</em> 是包含数据库序列化内容的文件集合。每个固定数据都有一个独有的名称，组成固定数据的文件可以分布在多个应用程序的多个目录中。</p>\n<aside class=\"admonition admonition-seealso\" role=\"note\">\n<p class=\"admonition-title\">See also</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.1/howto/initial-data/\"><span class=\"doc\">如何为模型提供初始数据</span></a></p></li>\n</ul>\n</aside>\n<section id=\"how-to-produce-a-fixture\">\n<h2>如何生成一个 fixture<a class=\"heading-anchor\" href=\"#how-to-produce-a-fixture\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>固定装置可以通过 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/django-admin/#django-admin-dumpdata\"><code class=\"xref std std-djadmin docutils literal notranslate\">manage.py dumpdata</code></a> 生成。还可以通过直接使用 <a class=\"reference internal\" href=\"/zh-hans/6.1/topics/serialization/\"><span class=\"doc\">序列化工具</span></a> 或甚至手工编写来生成自定义固定装置。</p>\n</section>\n<section id=\"how-to-use-a-fixture\">\n<h2>如何使用一个 fixture<a class=\"heading-anchor\" href=\"#how-to-use-a-fixture\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Fixture 可以用于在数据库中预填充数据以用于 <a class=\"reference internal\" href=\"/zh-hans/6.1/topics/testing/tools/#topics-testing-fixtures\"><span class=\"std std-ref\">测试</span></a>：</p>\n<div class=\"code-block\" data-language=\"python\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">class</span> <span class=\"nc\">MyTestCase</span><span class=\"p\">(</span>TestCase<span class=\"p\">):</span>\n    fixtures <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;fixture-label&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>或者使用 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/django-admin/#django-admin-loaddata\"><code class=\"xref std std-djadmin docutils literal notranslate\">loaddata</code></a> 命令提供一些 <a class=\"reference internal\" href=\"/zh-hans/6.1/howto/initial-data/#initial-data-via-fixtures\"><span class=\"std std-ref\">初始数据</span></a>：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin loaddata &lt;fixture label&gt;\n</code></pre></div>\n</section>\n<section id=\"how-fixtures-are-discovered\">\n<h2>Fixture 是如何被发现的<a class=\"heading-anchor\" href=\"#how-fixtures-are-discovered\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django 会在以下位置搜索固定装置：</p>\n<ol class=\"arabic simple\">\n<li><p>在每个安装的应用程序的 <code class=\"docutils literal notranslate\">fixtures</code> 目录中</p></li>\n<li><p>在 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/settings/#std-setting-FIXTURE_DIRS\"><code class=\"xref std std-setting docutils literal notranslate\">FIXTURE_DIRS</code></a> 设置中列出的任何目录中。</p></li>\n<li><p>在由固定数据命名的文字路径中</p></li>\n</ol>\n<p>Django 会加载在这些位置找到的与提供的固定装置名称匹配的所有固定装置。如果命名的固定装置有文件扩展名，那么只会加载该类型的固定装置。例如：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin loaddata mydata.json\n</code></pre></div>\n<p>将只加载名为 <code class=\"docutils literal notranslate\">mydata</code> 的 JSON 固定数据。固定数据扩展必须与 <a class=\"reference internal\" href=\"/zh-hans/6.1/topics/serialization/#serialization-formats\"><span class=\"std std-ref\">序列化器</span></a> 的注册名称相对应（例如，<code class=\"docutils literal notranslate\">json</code> 或 <code class=\"docutils literal notranslate\">xml</code>）。</p>\n<p>如果省略扩展名，Django 将搜索所有可用的固定装置类型以查找匹配的固定装置。例如：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin loaddata mydata\n</code></pre></div>\n<p>将寻找任何固定数据类型的名为 <code class=\"docutils literal notranslate\">mydata</code> 的固定数据。如果一个固定数据目录包含 <code class=\"docutils literal notranslate\">mydata.json</code>，该固定数据将作为 JSON 固定数据加载。</p>\n<p>命名的固定装置可以包含目录组件。这些目录将包含在搜索路径中。例如：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin loaddata foo/bar/mydata.json\n</code></pre></div>\n<p>会在每个已安装的应用程序中搜索 <code class=\"docutils literal notranslate\">&lt;app_label&gt;/fixtures/foo/bar/mydata.json</code>，在 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/settings/#std-setting-FIXTURE_DIRS\"><code class=\"xref std std-setting docutils literal notranslate\">FIXTURE_DIRS</code></a> 中的每个目录中搜索 <code class=\"docutils literal notranslate\">&lt;dirname&gt;/foo/bar/mydata.json</code>，以及字面路径 <code class=\"docutils literal notranslate\">foo/bar/mydata.json</code>。</p>\n<section id=\"fixtures-loading-order\">\n<h3>固定装置的加载顺序：<a class=\"heading-anchor\" href=\"#fixtures-loading-order\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>可以在同一次调用中指定多个固定装置。例如：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin loaddata mammals birds insects\n</code></pre></div>\n<p>或者在测试用例类中：</p>\n<div class=\"code-block\" data-language=\"python\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">class</span> <span class=\"nc\">AnimalTestCase</span><span class=\"p\">(</span>TestCase<span class=\"p\">):</span>\n    fixtures <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;mammals&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;birds&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;insects&quot;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>固定装置加载的顺序遵循它们在列表中列出的顺序，无论是在使用管理命令时还是在测试用例类中如上所示。</p>\n<p>在这些示例中，首先将加载所有应用程序中命名为 <code class=\"docutils literal notranslate\">mammals</code> 的固定装置（按照 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\">INSTALLED_APPS</code></a> 中应用程序的定义顺序）。随后，将加载所有的 <code class=\"docutils literal notranslate\">birds</code> 固定装置，然后是所有的 <code class=\"docutils literal notranslate\">insects</code> 固定装置。</p>\n<p>请注意，如果数据库后端支持行级约束，这些约束将在事务结束时进行检查。如果跨固定装置存在关联关系，并且数据库配置不支持延迟约束检查，可能会导致加载错误（请参考 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/constraint-foreign-key.html\">MySQL</a> 文档以获取示例）。</p>\n</section>\n</section>\n<section id=\"how-fixtures-are-saved-to-the-database\">\n<h2>Fixture 是如何保存到数据库中的<a class=\"heading-anchor\" href=\"#how-fixtures-are-saved-to-the-database\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>When fixture files are processed, the data is saved to the database as is.\nModel defined <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/models/instances/#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\">save()</code></a> methods are not called, and\nany <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/signals/#django.db.models.signals.pre_save\" title=\"django.db.models.signals.pre_save\"><code class=\"xref py py-data docutils literal notranslate\">pre_save</code></a>,\n<a class=\"reference internal\" href=\"/zh-hans/6.1/ref/signals/#django.db.models.signals.post_save\" title=\"django.db.models.signals.post_save\"><code class=\"xref py py-data docutils literal notranslate\">post_save</code></a>, or\n<a class=\"reference internal\" href=\"/zh-hans/6.1/ref/signals/#django.db.models.signals.m2m_changed\" title=\"django.db.models.signals.m2m_changed\"><code class=\"xref py py-data docutils literal notranslate\">m2m_changed</code></a> signals will be called with\n<code class=\"docutils literal notranslate\">raw=True</code> since the instance only contains attributes that are local to the\nmodel. You may, for example, want to disable handlers that access\nrelated fields that aren't present during fixture loading and would otherwise\nraise an exception:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.db.models.signals</span> <span class=\"kn\">import</span> post_save\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> MyModel\n\n\n<span class=\"k\">def</span> <span class=\"nf\">my_handler</span><span class=\"p\">(</span><span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n    <span class=\"c1\"># disable the handler during fixture loading</span>\n    <span class=\"k\">if</span> kwargs<span class=\"p\">[</span><span class=\"s2\">&quot;raw&quot;</span><span class=\"p\">]:</span>\n        <span class=\"k\">return</span>\n    <span class=\"o\">...</span>\n\n\npost_save<span class=\"o\">.</span>connect<span class=\"p\">(</span>my_handler<span class=\"p\">,</span> sender<span class=\"o\">=</span>MyModel<span class=\"p\">)</span>\n</code></pre></div>\n<p>你也可以写一个装饰器来封装这个逻辑：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">functools</span> <span class=\"kn\">import</span> wraps\n\n\n<span class=\"k\">def</span> <span class=\"nf\">disable_for_loaddata</span><span class=\"p\">(</span>signal_handler<span class=\"p\">):</span>\n    <span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    Decorator that turns off signal handlers when loading fixture data.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n\n    <span class=\"nd\">@wraps</span><span class=\"p\">(</span>signal_handler<span class=\"p\">)</span>\n    <span class=\"k\">def</span> <span class=\"nf\">wrapper</span><span class=\"p\">(</span><span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n        <span class=\"k\">if</span> kwargs<span class=\"p\">[</span><span class=\"s2\">&quot;raw&quot;</span><span class=\"p\">]:</span>\n            <span class=\"k\">return</span>\n        signal_handler<span class=\"p\">(</span><span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">)</span>\n\n    <span class=\"k\">return</span> wrapper\n\n\n<span class=\"nd\">@disable_for_loaddata</span>\n<span class=\"k\">def</span> <span class=\"nf\">my_handler</span><span class=\"p\">(</span><span class=\"o\">**</span>kwargs<span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>请注意，这个逻辑会在固定装置被反序列化时禁用信号，而不仅仅是在 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/django-admin/#django-admin-loaddata\"><code class=\"xref std std-djadmin docutils literal notranslate\">loaddata</code></a> 过程中。</p>\n<aside class=\"version-note version-changed\" data-version=\"6.1\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 6.1</p><p>The <code class=\"docutils literal notranslate\">raw</code> argument was added to <code class=\"docutils literal notranslate\">m2m_changed</code> signals.</p>\n</aside>\n</section>\n<section id=\"compressed-fixtures\">\n<h2>压缩的固定数据<a class=\"heading-anchor\" href=\"#compressed-fixtures\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>固定装置可以以 <code class=\"docutils literal notranslate\">zip</code>、<code class=\"docutils literal notranslate\">gz</code>、<code class=\"docutils literal notranslate\">bz2</code>、<code class=\"docutils literal notranslate\">lzma</code> 或 <code class=\"docutils literal notranslate\">xz</code> 格式进行压缩。例如：</p>\n<div class=\"code-block\" data-language=\"shell\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code>django-admin loaddata mydata.json\n</code></pre></div>\n<p>将寻找任何 <code class=\"docutils literal notranslate\">mydata.json</code>、<code class=\"docutils literal notranslate\">mydata.json.zip</code>、<code class=\"docutils literal notranslate\">mydata.json.gz</code>、<code class=\"docutils literal notranslate\">mydata.json.bz2</code>、<code class=\"docutils literal notranslate\">mydata.json.lzma</code> 或 <code class=\"docutils literal notranslate\">mydata.json.xz</code>。压缩档案中包含的第一个文件被使用。</p>\n<p>请注意，如果发现具有相同名称但不同固定装置类型的两个固定装置（例如，在同一固定装置目录中找到了 <code class=\"docutils literal notranslate\">mydata.json</code> 和 <code class=\"docutils literal notranslate\">mydata.xml.gz</code>），则会中止固定装置的安装，并且在 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/django-admin/#django-admin-loaddata\"><code class=\"xref std std-djadmin docutils literal notranslate\">loaddata</code></a> 调用中安装的任何数据都将从数据库中删除。</p>\n<aside class=\"admonition-mysql-with-myisam-and-fixtures admonition\" role=\"note\">\n<p class=\"admonition-title\">使用 MyISAM 的 MySQL 与固定数据</p>\n<p>MySQL 的 MyISAM 存储引擎不支持事务或约束，所以如果你使用 MyISAM，你不会得到固定数据的数据验证，如果发现多个事务文件，也不会有回滚。</p>\n</aside>\n</section>\n<section id=\"database-specific-fixtures\">\n<h2>特定数据库的固定数据<a class=\"heading-anchor\" href=\"#database-specific-fixtures\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>如果你在一个多数据库配置中，你可能会有想加载到一个数据库，但不加载到另一个数据库的固定数据。在这种情况下，你可以在固定数据的名称中添加一个数据库标识符。</p>\n<p>例如，如果你的 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\">DATABASES</code></a> 设置中定义了一个名为 <code class=\"docutils literal notranslate\">users</code> 的数据库，那么将固定装置命名为 <code class=\"docutils literal notranslate\">mydata.users.json</code> 或 <code class=\"docutils literal notranslate\">mydata.users.json.gz</code>，那么这个固定装置只会在你指定要加载数据到 <code class=\"docutils literal notranslate\">users</code> 数据库时才会被加载。</p>\n</section>","rootId":"fixtures","toc":[{"title":"如何生成一个 fixture","anchor":"how-to-produce-a-fixture","children":[]},{"title":"如何使用一个 fixture","anchor":"how-to-use-a-fixture","children":[]},{"title":"Fixture 是如何被发现的","anchor":"how-fixtures-are-discovered","children":[{"title":"固定装置的加载顺序：","anchor":"fixtures-loading-order","children":[]}]},{"title":"Fixture 是如何保存到数据库中的","anchor":"how-fixtures-are-saved-to-the-database","children":[]},{"title":"压缩的固定数据","anchor":"compressed-fixtures","children":[]},{"title":"特定数据库的固定数据","anchor":"database-specific-fixtures","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/6.1/topics/"},{"docname":"topics/db/index","title":"模型和数据库","url":"/zh-hans/6.1/topics/db/"}],"prev":{"docname":"topics/db/instrumentation","title":"数据库工具","url":"/zh-hans/6.1/topics/db/instrumentation/"},"next":{"docname":"topics/db/examples/index","title":"模型关联 API 用法示例","url":"/zh-hans/6.1/topics/db/examples/"},"formats":{"html":"/zh-hans/6.1/topics/db/fixtures/","markdown":"/zh-hans/6.1/topics/db/fixtures.md","json":"/zh-hans/6.1/topics/db/fixtures.json"},"source":"https://github.com/django/django/blob/stable/6.1.x/docs/topics/db/fixtures.txt","official":"https://docs.djangoproject.com/zh-hans/6.1/topics/db/fixtures/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}