{"title":"编写数据库迁移语句","version":"3.0","locale":"zh-hans","docname":"howto/writing-migrations","url":"/zh-hans/3.0/howto/writing-migrations/","canonical":"https://djangodocs.dev/zh-hans/3.0/howto/writing-migrations/","summary":"本文介绍了如何为可能遇到的不同场景组织和编写数据库迁移。关于迁移的介绍性资料，参考 专题指南 。 数据迁移和多种数据库 Link to this heading # 使用多种数据库时，你可能需要指定是否为特定数据库运行迁移。例如，你可能 只想 为特定数据库运行迁移。 为此，你可以在 RunPython…","html":"<h1>编写数据库迁移语句<a class=\"heading-anchor\" href=\"#writing-database-migrations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>本文介绍了如何为可能遇到的不同场景组织和编写数据库迁移。关于迁移的介绍性资料，参考 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/migrations/\"><span class=\"doc\">专题指南</span></a>。</p>\n<section id=\"data-migrations-and-multiple-databases\">\n<span id=\"id1\"></span><h2>数据迁移和多种数据库<a class=\"heading-anchor\" href=\"#data-migrations-and-multiple-databases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>使用多种数据库时，你可能需要指定是否为特定数据库运行迁移。例如，你可能 <strong>只想</strong> 为特定数据库运行迁移。</p>\n<p>为此，你可以在 <code class=\"docutils literal notranslate\"><span class=\"pre\">RunPython</span></code> 操作中检查数据库连接别名，通过查看 <code class=\"docutils literal notranslate\"><span class=\"pre\">schema_editor.connection.alias</span></code> 属性:</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=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">forwards</span><span class=\"p\">(</span><span class=\"n\">apps</span><span class=\"p\">,</span> <span class=\"n\">schema_editor</span><span class=\"p\">):</span>\n    <span class=\"k\">if</span> <span class=\"n\">schema_editor</span><span class=\"o\">.</span><span class=\"n\">connection</span><span class=\"o\">.</span><span class=\"n\">alias</span> <span class=\"o\">!=</span> <span class=\"s1\">&#39;default&#39;</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span>\n    <span class=\"c1\"># Your migration code goes here</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"c1\"># Dependencies to other migrations</span>\n    <span class=\"p\">]</span>\n\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunPython</span><span class=\"p\">(</span><span class=\"n\">forwards</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></div>\n<p>你也能提供会以 <code class=\"docutils literal notranslate\"><span class=\"pre\">**hints</span></code> 传递给数据库路由器的 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/db/multi-db/#allow_migrate\" title=\"allow_migrate\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">allow_migrate()</span></code></a> 方法的提示：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">myapp/dbrouters.py</figcaption>\n<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=\"w\"> </span><span class=\"nc\">MyRouter</span><span class=\"p\">:</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">allow_migrate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">db</span><span class=\"p\">,</span> <span class=\"n\">app_label</span><span class=\"p\">,</span> <span class=\"n\">model_name</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">hints</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"s1\">&#39;target_db&#39;</span> <span class=\"ow\">in</span> <span class=\"n\">hints</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">db</span> <span class=\"o\">==</span> <span class=\"n\">hints</span><span class=\"p\">[</span><span class=\"s1\">&#39;target_db&#39;</span><span class=\"p\">]</span>\n        <span class=\"k\">return</span> <span class=\"kc\">True</span>\n</code></pre></figure>\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=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">forwards</span><span class=\"p\">(</span><span class=\"n\">apps</span><span class=\"p\">,</span> <span class=\"n\">schema_editor</span><span class=\"p\">):</span>\n    <span class=\"c1\"># Your migration code goes here</span>\n    <span class=\"o\">...</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"c1\"># Dependencies to other migrations</span>\n    <span class=\"p\">]</span>\n\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunPython</span><span class=\"p\">(</span><span class=\"n\">forwards</span><span class=\"p\">,</span> <span class=\"n\">hints</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;target_db&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;default&#39;</span><span class=\"p\">}),</span>\n    <span class=\"p\">]</span>\n</code></pre></div>\n<p>若你的 <code class=\"docutils literal notranslate\"><span class=\"pre\">RunPython</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">RunSQL</span></code> 操作只影响了一个模型，为其传入 <code class=\"docutils literal notranslate\"><span class=\"pre\">model_name</span></code> 作为提示，使其对路由器更加透明。这对可复用的和第三方应用特别重要。</p>\n</section>\n<section id=\"migrations-that-add-unique-fields\">\n<h2>添加独一无二字段的迁移<a class=\"heading-anchor\" href=\"#migrations-that-add-unique-fields\"><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/3.0/ref/models/fields/#django.db.models.UUIDField\" title=\"django.db.models.UUIDField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">UUIDField</span></code></a>。根据你的需要修改对应字段。</p>\n<ul>\n<li><p>在模型中以 <code class=\"docutils literal notranslate\"><span class=\"pre\">default=uuid.uuid4</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">unique=True</span></code> 参数添加该字段（根据字段类型，为其选择一个合适的默认值）。</p></li>\n<li><p>运行 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-makemigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">makemigrations</span></code></a> 命令。这将生成一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">AddField</span></code> 操作的迁移。</p></li>\n<li><p>通过运行 <code class=\"docutils literal notranslate\"><span class=\"pre\">makemigrations</span> <span class=\"pre\">myapp</span> <span class=\"pre\">--empty</span></code> 两次为同一应用生成两个相同的空迁移文件。我们已在以下例子中将迁移文件重命名成有意义的名字。</p></li>\n<li><p>从自动生成的迁移（3个新文件中的第一个）中将 <code class=\"docutils literal notranslate\"><span class=\"pre\">AddField</span></code> 操作拷贝至上一个迁移，将 <code class=\"docutils literal notranslate\"><span class=\"pre\">AddField</span></code> 改为 <code class=\"docutils literal notranslate\"><span class=\"pre\">AlterField</span></code>，添加 <code class=\"docutils literal notranslate\"><span class=\"pre\">uuid</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">models</span></code> 的导入。例子：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">0006_remove_uuid_null.py</figcaption>\n<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=\"c1\"># Generated by Django A.B on YYYY-MM-DD HH:MM</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span><span class=\"p\">,</span> <span class=\"n\">models</span>\n<span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">uuid</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;myapp&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0005_populate_uuid_values&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">AlterField</span><span class=\"p\">(</span>\n            <span class=\"n\">model_name</span><span class=\"o\">=</span><span class=\"s1\">&#39;mymodel&#39;</span><span class=\"p\">,</span>\n            <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;uuid&#39;</span><span class=\"p\">,</span>\n            <span class=\"n\">field</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">UUIDField</span><span class=\"p\">(</span><span class=\"n\">default</span><span class=\"o\">=</span><span class=\"n\">uuid</span><span class=\"o\">.</span><span class=\"n\">uuid4</span><span class=\"p\">,</span> <span class=\"n\">unique</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">),</span>\n        <span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></figure>\n</li>\n<li><p>编辑第一个迁移文件。生成的迁移类应该看起来像这样：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">0004_add_uuid_field.py</figcaption>\n<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=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;myapp&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0003_auto_20150129_1705&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">AddField</span><span class=\"p\">(</span>\n            <span class=\"n\">model_name</span><span class=\"o\">=</span><span class=\"s1\">&#39;mymodel&#39;</span><span class=\"p\">,</span>\n            <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;uuid&#39;</span><span class=\"p\">,</span>\n            <span class=\"n\">field</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">UUIDField</span><span class=\"p\">(</span><span class=\"n\">default</span><span class=\"o\">=</span><span class=\"n\">uuid</span><span class=\"o\">.</span><span class=\"n\">uuid4</span><span class=\"p\">,</span> <span class=\"n\">unique</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">),</span>\n        <span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></figure>\n<p>将 <code class=\"docutils literal notranslate\"><span class=\"pre\">unique=True</span></code> 改为 <code class=\"docutils literal notranslate\"><span class=\"pre\">null=True</span></code>——这将创建中间 null 字段，并延迟创建唯一性约束，直到我们已为所以行填充了唯一值。</p>\n</li>\n<li><p>在第一个空的迁移文件中，添加一个 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/migration-operations/#django.db.migrations.operations.RunPython\" title=\"django.db.migrations.operations.RunPython\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RunPython</span></code></a> 或 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/migration-operations/#django.db.migrations.operations.RunSQL\" title=\"django.db.migrations.operations.RunSQL\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RunSQL</span></code></a> 操作，为每个已存在的行创建一个唯一值（本例中 UUID）。同时添加 <code class=\"docutils literal notranslate\"><span class=\"pre\">uuid</span></code> 的导入。例子：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">0005_populate_uuid_values.py</figcaption>\n<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=\"c1\"># Generated by Django A.B on YYYY-MM-DD HH:MM</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span>\n<span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">uuid</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">gen_uuid</span><span class=\"p\">(</span><span class=\"n\">apps</span><span class=\"p\">,</span> <span class=\"n\">schema_editor</span><span class=\"p\">):</span>\n    <span class=\"n\">MyModel</span> <span class=\"o\">=</span> <span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">get_model</span><span class=\"p\">(</span><span class=\"s1\">&#39;myapp&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;MyModel&#39;</span><span class=\"p\">)</span>\n    <span class=\"k\">for</span> <span class=\"n\">row</span> <span class=\"ow\">in</span> <span class=\"n\">MyModel</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">():</span>\n        <span class=\"n\">row</span><span class=\"o\">.</span><span class=\"n\">uuid</span> <span class=\"o\">=</span> <span class=\"n\">uuid</span><span class=\"o\">.</span><span class=\"n\">uuid4</span><span class=\"p\">()</span>\n        <span class=\"n\">row</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">update_fields</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s1\">&#39;uuid&#39;</span><span class=\"p\">])</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;myapp&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0004_add_uuid_field&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"c1\"># omit reverse_code=... if you don&#39;t want the migration to be reversible.</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunPython</span><span class=\"p\">(</span><span class=\"n\">gen_uuid</span><span class=\"p\">,</span> <span class=\"n\">reverse_code</span><span class=\"o\">=</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunPython</span><span class=\"o\">.</span><span class=\"n\">noop</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></figure>\n</li>\n<li><p>现在你能像往常一样用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> 应用迁移了。</p>\n<p>注意，若你允许运行迁移时创建对象可能会造成竞争。 <code class=\"docutils literal notranslate\"><span class=\"pre\">AddField</span></code> 后和 <code class=\"docutils literal notranslate\"><span class=\"pre\">RunPython</span></code> 前创建的对象保留原先重写的 <code class=\"docutils literal notranslate\"><span class=\"pre\">uuid</span></code> 值。</p>\n</li>\n</ul>\n<section id=\"non-atomic-migrations\">\n<span id=\"id2\"></span><h3>非原子性迁移<a class=\"heading-anchor\" href=\"#non-atomic-migrations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>对于支持 DDL 事务的数据库 (SQLite and PostgreSQL)，迁移默认运行在事务内。对于类似在大数据表上运行数据迁移的场景，你可以通过将 <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> 属性置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> 避免在事务中运行迁移:</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=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n    <span class=\"n\">atomic</span> <span class=\"o\">=</span> <span class=\"kc\">False</span>\n</code></pre></div>\n<p>在这样的迁移种，所有的操作运行时都不含事务。通过使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/db/transactions/#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> 或为 <code class=\"docutils literal notranslate\"><span class=\"pre\">RunPython</span></code> 传入 <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic=True</span></code> 能将部分迁移置于事务之中。</p>\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\">import</span><span class=\"w\"> </span><span class=\"nn\">uuid</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span><span class=\"p\">,</span> <span class=\"n\">transaction</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">gen_uuid</span><span class=\"p\">(</span><span class=\"n\">apps</span><span class=\"p\">,</span> <span class=\"n\">schema_editor</span><span class=\"p\">):</span>\n    <span class=\"n\">MyModel</span> <span class=\"o\">=</span> <span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">get_model</span><span class=\"p\">(</span><span class=\"s1\">&#39;myapp&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;MyModel&#39;</span><span class=\"p\">)</span>\n    <span class=\"k\">while</span> <span class=\"n\">MyModel</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">uuid__isnull</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">exists</span><span class=\"p\">():</span>\n        <span class=\"k\">with</span> <span class=\"n\">transaction</span><span class=\"o\">.</span><span class=\"n\">atomic</span><span class=\"p\">():</span>\n            <span class=\"k\">for</span> <span class=\"n\">row</span> <span class=\"ow\">in</span> <span class=\"n\">MyModel</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">uuid__isnull</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)[:</span><span class=\"mi\">1000</span><span class=\"p\">]:</span>\n                <span class=\"n\">row</span><span class=\"o\">.</span><span class=\"n\">uuid</span> <span class=\"o\">=</span> <span class=\"n\">uuid</span><span class=\"o\">.</span><span class=\"n\">uuid4</span><span class=\"p\">()</span>\n                <span class=\"n\">row</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n    <span class=\"n\">atomic</span> <span class=\"o\">=</span> <span class=\"kc\">False</span>\n\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunPython</span><span class=\"p\">(</span><span class=\"n\">gen_uuid</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> 属性对不支持 DDL 事务的数据库没有影响（例如 MySQL，Oracle）。（MySQL 的 <a class=\"reference external\" href=\"https://dev.mysql.com/doc/refman/en/atomic-ddl.html\">原子性 DDL 语句支持</a> 指向独立的语句，而不是封装在能回滚的事务中的多句语句。）</p>\n</section>\n</section>\n<section id=\"controlling-the-order-of-migrations\">\n<h2>控制迁移顺序<a class=\"heading-anchor\" href=\"#controlling-the-order-of-migrations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django 不是通过迁移的名字决定迁移执行顺序，而是通过在 <code class=\"docutils literal notranslate\"><span class=\"pre\">迁移</span></code> 类上使用两个属性：  <code class=\"docutils literal notranslate\"><span class=\"pre\">dependencies</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">run_before</span></code>。</p>\n<p>若你用过 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-makemigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">makemigrations</span></code></a> 命令，你可能早已在运行时见过 <code class=\"docutils literal notranslate\"><span class=\"pre\">dependencies</span></code>，因为自动创建的迁移将此定义为其创建过程的一部分。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">依赖</span></code> 属性像这样申明:</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=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;myapp&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0123_the_previous_migration&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></div>\n<p>通常这就够用了，但是有很多次，你总是需要确认你的迁移运行在其它迁移 <em>之前</em>。例如，这对于让第三方应用的迁移运行在替换 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></a> 之后就很有用。</p>\n<p>要实现此目的，将所有需要先运行的迁移置于你的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Migration</span></code> 类的 <code class=\"docutils literal notranslate\"><span class=\"pre\">run_before</span></code> 属性:</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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"n\">run_before</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;third_party_app&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0001_do_awesome&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></div>\n<p>尽可能使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">dependencies</span></code>，而不是 <code class=\"docutils literal notranslate\"><span class=\"pre\">run_before</span></code>。只有在在特定迁移中添加 <code class=\"docutils literal notranslate\"><span class=\"pre\">dependencies</span></code> 使其运行于你编写的迁移之后是没希望的和不切实际的情况下，你才能使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">run_before</span></code>。</p>\n</section>\n<section id=\"migrating-data-between-third-party-apps\">\n<h2>在第三方应用程序中迁移数据<a class=\"heading-anchor\" href=\"#migrating-data-between-third-party-apps\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>你可以使用数据迁移把数据从一个第三方应用程序中转移到另一个。</p>\n<p>如果你计划要移除旧应用程序，则需要根据是否安装旧应用程序来设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">依赖</span></code> 属性。否则，一旦你卸载旧应用程序，就会缺失依赖项。同样，你需要在调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">app.get_model()</span></code> 时捕获 <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#LookupError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">LookupError</span></code></a>，前者在旧应用程序中检索模型。这种方法允许你在任何地方部署项目，而无需先安装并且卸载旧应用程序。</p>\n<p>这是一个迁移示例：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">myapp/migrations/0124_move_old_app_to_new_app.py</figcaption>\n<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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.apps</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">apps</span> <span class=\"k\">as</span> <span class=\"n\">global_apps</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">forwards</span><span class=\"p\">(</span><span class=\"n\">apps</span><span class=\"p\">,</span> <span class=\"n\">schema_editor</span><span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"n\">OldModel</span> <span class=\"o\">=</span> <span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">get_model</span><span class=\"p\">(</span><span class=\"s1\">&#39;old_app&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;OldModel&#39;</span><span class=\"p\">)</span>\n    <span class=\"k\">except</span> <span class=\"ne\">LookupError</span><span class=\"p\">:</span>\n        <span class=\"c1\"># The old app isn&#39;t installed.</span>\n        <span class=\"k\">return</span>\n\n    <span class=\"n\">NewModel</span> <span class=\"o\">=</span> <span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">get_model</span><span class=\"p\">(</span><span class=\"s1\">&#39;new_app&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;NewModel&#39;</span><span class=\"p\">)</span>\n    <span class=\"n\">NewModel</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">bulk_create</span><span class=\"p\">(</span>\n        <span class=\"n\">NewModel</span><span class=\"p\">(</span><span class=\"n\">new_attribute</span><span class=\"o\">=</span><span class=\"n\">old_object</span><span class=\"o\">.</span><span class=\"n\">old_attribute</span><span class=\"p\">)</span>\n        <span class=\"k\">for</span> <span class=\"n\">old_object</span> <span class=\"ow\">in</span> <span class=\"n\">OldModel</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n    <span class=\"p\">)</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunPython</span><span class=\"p\">(</span><span class=\"n\">forwards</span><span class=\"p\">,</span> <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunPython</span><span class=\"o\">.</span><span class=\"n\">noop</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;myapp&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0123_the_previous_migration&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;new_app&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0001_initial&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n\n    <span class=\"k\">if</span> <span class=\"n\">global_apps</span><span class=\"o\">.</span><span class=\"n\">is_installed</span><span class=\"p\">(</span><span class=\"s1\">&#39;old_app&#39;</span><span class=\"p\">):</span>\n        <span class=\"n\">dependencies</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">((</span><span class=\"s1\">&#39;old_app&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0001_initial&#39;</span><span class=\"p\">))</span>\n</code></pre></figure>\n<p>另外在迁移未执行时，请考虑好什么是你想要发生的。你可以什么都不做（就像上面的示例）或者从新应用中移除一些或全部的数据。相应的调整 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/migration-operations/#django.db.migrations.operations.RunPython\" title=\"django.db.migrations.operations.RunPython\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">RunPython</span></code></a> 操作的第二个参数。</p>\n</section>\n<section id=\"changing-a-manytomanyfield-to-use-a-through-model\">\n<span id=\"id3\"></span><h2>通过使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">through</span></code> 模型来更改 <code class=\"docutils literal notranslate\"><span class=\"pre\">ManyToManyField</span></code> 字段。<a class=\"heading-anchor\" href=\"#changing-a-manytomanyfield-to-use-a-through-model\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>假如你通过使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">through</span></code> 模型来改变  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ManyToManyField</span></code></a> ，默认的迁移操作会删除现存的表并创建一个新的表，来解耦现存的关联。为了避免这种情况，你可以使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/migration-operations/#django.db.migrations.operations.SeparateDatabaseAndState\" title=\"django.db.migrations.operations.SeparateDatabaseAndState\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SeparateDatabaseAndState</span></code></a>  来重命名现存的表为另一个新的表名，同时告诉迁移自动探测器新的模型已经被建立了。你可以通过 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-sqlmigrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">sqlmigrate</span></code></a> 或 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-dbshell\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">dbshell</span></code></a> 来查看现有的表名。你可以通过模型的 <code class=\"docutils literal notranslate\"><span class=\"pre\">_meta.db_table</span></code> 属性来检查新的表名。新的 <code class=\"docutils literal notranslate\"><span class=\"pre\">through</span></code>  模型应该使用与那些 <code class=\"docutils literal notranslate\"><span class=\"pre\">外键</span></code> 们相同的名称。同时，假如需要其他额外的字段，它们应该添加在  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/migration-operations/#django.db.migrations.operations.SeparateDatabaseAndState\" title=\"django.db.migrations.operations.SeparateDatabaseAndState\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SeparateDatabaseAndState</span></code></a> 操作之后。</p>\n<p>例如，假如你有一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Book</span></code> 模型，它通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">ManyToManyField</span></code>  链接 <code class=\"docutils literal notranslate\"><span class=\"pre\">Author</span></code> 模型，我们可以通过像下面这样添加一个带有新字段 <code class=\"docutils literal notranslate\"><span class=\"pre\">is_primary</span></code> 的中间模型 <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorBook</span></code></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=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span><span class=\"p\">,</span> <span class=\"n\">models</span>\n<span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">django.db.models.deletion</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;core&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0001_initial&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">SeparateDatabaseAndState</span><span class=\"p\">(</span>\n            <span class=\"n\">database_operations</span><span class=\"o\">=</span><span class=\"p\">[</span>\n                <span class=\"c1\"># Old table name from checking with sqlmigrate, new table</span>\n                <span class=\"c1\"># name from AuthorBook._meta.db_table.</span>\n                <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunSQL</span><span class=\"p\">(</span>\n                    <span class=\"n\">sql</span><span class=\"o\">=</span><span class=\"s1\">&#39;ALTER TABLE core_book_authors RENAME TO core_authorbook&#39;</span><span class=\"p\">,</span>\n                    <span class=\"n\">reverse_sql</span><span class=\"o\">=</span><span class=\"s1\">&#39;ALTER TABLE core_authorbook RENAME TO core_book_authors&#39;</span><span class=\"p\">,</span>\n                <span class=\"p\">),</span>\n            <span class=\"p\">],</span>\n            <span class=\"n\">state_operations</span><span class=\"o\">=</span><span class=\"p\">[</span>\n                <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">CreateModel</span><span class=\"p\">(</span>\n                    <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;AuthorBook&#39;</span><span class=\"p\">,</span>\n                    <span class=\"n\">fields</span><span class=\"o\">=</span><span class=\"p\">[</span>\n                        <span class=\"p\">(</span>\n                            <span class=\"s1\">&#39;id&#39;</span><span class=\"p\">,</span>\n                            <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">AutoField</span><span class=\"p\">(</span>\n                                <span class=\"n\">auto_created</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span>\n                                <span class=\"n\">primary_key</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span>\n                                <span class=\"n\">serialize</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">,</span>\n                                <span class=\"n\">verbose_name</span><span class=\"o\">=</span><span class=\"s1\">&#39;ID&#39;</span><span class=\"p\">,</span>\n                            <span class=\"p\">),</span>\n                        <span class=\"p\">),</span>\n                        <span class=\"p\">(</span>\n                            <span class=\"s1\">&#39;author&#39;</span><span class=\"p\">,</span>\n                            <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ForeignKey</span><span class=\"p\">(</span>\n                                <span class=\"n\">on_delete</span><span class=\"o\">=</span><span class=\"n\">django</span><span class=\"o\">.</span><span class=\"n\">db</span><span class=\"o\">.</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">deletion</span><span class=\"o\">.</span><span class=\"n\">DO_NOTHING</span><span class=\"p\">,</span>\n                                <span class=\"n\">to</span><span class=\"o\">=</span><span class=\"s1\">&#39;core.Author&#39;</span><span class=\"p\">,</span>\n                            <span class=\"p\">),</span>\n                        <span class=\"p\">),</span>\n                        <span class=\"p\">(</span>\n                            <span class=\"s1\">&#39;book&#39;</span><span class=\"p\">,</span>\n                            <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ForeignKey</span><span class=\"p\">(</span>\n                                <span class=\"n\">on_delete</span><span class=\"o\">=</span><span class=\"n\">django</span><span class=\"o\">.</span><span class=\"n\">db</span><span class=\"o\">.</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">deletion</span><span class=\"o\">.</span><span class=\"n\">DO_NOTHING</span><span class=\"p\">,</span>\n                                <span class=\"n\">to</span><span class=\"o\">=</span><span class=\"s1\">&#39;core.Book&#39;</span><span class=\"p\">,</span>\n                            <span class=\"p\">),</span>\n                        <span class=\"p\">),</span>\n                    <span class=\"p\">],</span>\n                <span class=\"p\">),</span>\n                <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">AlterField</span><span class=\"p\">(</span>\n                    <span class=\"n\">model_name</span><span class=\"o\">=</span><span class=\"s1\">&#39;book&#39;</span><span class=\"p\">,</span>\n                    <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;authors&#39;</span><span class=\"p\">,</span>\n                    <span class=\"n\">field</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ManyToManyField</span><span class=\"p\">(</span>\n                        <span class=\"n\">to</span><span class=\"o\">=</span><span class=\"s1\">&#39;core.Author&#39;</span><span class=\"p\">,</span>\n                        <span class=\"n\">through</span><span class=\"o\">=</span><span class=\"s1\">&#39;core.AuthorBook&#39;</span><span class=\"p\">,</span>\n                    <span class=\"p\">),</span>\n                <span class=\"p\">),</span>\n            <span class=\"p\">],</span>\n        <span class=\"p\">),</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">AddField</span><span class=\"p\">(</span>\n            <span class=\"n\">model_name</span><span class=\"o\">=</span><span class=\"s1\">&#39;authorbook&#39;</span><span class=\"p\">,</span>\n            <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;is_primary&#39;</span><span class=\"p\">,</span>\n            <span class=\"n\">field</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">BooleanField</span><span class=\"p\">(</span><span class=\"n\">default</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">),</span>\n        <span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></div>\n</section>\n<section id=\"changing-an-unmanaged-model-to-managed\">\n<h2>将非托管模型变为托管的<a class=\"heading-anchor\" href=\"#changing-an-unmanaged-model-to-managed\"><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/3.0/ref/models/options/#django.db.models.Options.managed\" title=\"django.db.models.Options.managed\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">managed=False</span></code></a>) 变为托管的，你必须移除 <code class=\"docutils literal notranslate\"><span class=\"pre\">managed=False</span></code> 并且在对此模型做其他模式相关的改变前生成一次迁移，因为如果迁移中出现模式改变，对 <code class=\"docutils literal notranslate\"><span class=\"pre\">Meta.managed</span></code> 的修改操作不会被执行。</p>\n</section>","rootId":"writing-database-migrations","toc":[{"title":"数据迁移和多种数据库","anchor":"data-migrations-and-multiple-databases","children":[]},{"title":"添加独一无二字段的迁移","anchor":"migrations-that-add-unique-fields","children":[{"title":"非原子性迁移","anchor":"non-atomic-migrations","children":[]}]},{"title":"控制迁移顺序","anchor":"controlling-the-order-of-migrations","children":[]},{"title":"在第三方应用程序中迁移数据","anchor":"migrating-data-between-third-party-apps","children":[]},{"title":"通过使用 through 模型来更改 ManyToManyField 字段。","anchor":"changing-a-manytomanyfield-to-use-a-through-model","children":[]},{"title":"将非托管模型变为托管的","anchor":"changing-an-unmanaged-model-to-managed","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"操作指南","url":"/zh-hans/3.0/howto/"}],"prev":{"docname":"howto/windows","title":"如何在 Windows 上安装 Django","url":"/zh-hans/3.0/howto/windows/"},"next":{"docname":"faq/index","title":"Django FAQ","url":"/zh-hans/3.0/faq/"},"formats":{"html":"/zh-hans/3.0/howto/writing-migrations/","markdown":"/zh-hans/3.0/howto/writing-migrations.md","json":"/zh-hans/3.0/howto/writing-migrations.json"},"source":"https://github.com/django/django/blob/stable/3.0.x/docs/howto/writing-migrations.txt","official":"https://docs.djangoproject.com/zh-hans/3.0/howto/writing-migrations/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}