{"title":"模型实例参考","version":"4.1","locale":"zh-hans","docname":"ref/models/instances","url":"/zh-hans/4.1/ref/models/instances/","canonical":"https://djangodocs.dev/zh-hans/4.1/ref/models/instances/","summary":"本文档描述了 Model API 的细节。它建立在模型和数据库查询指南中所介绍的材料基础上，因此，在阅读本文档之前，你可能需要阅读并理解这些文档。","html":"<h1>模型实例参考<a class=\"heading-anchor\" href=\"#model-instance-reference\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>本文档描述了 <code class=\"docutils literal notranslate\">Model</code> API 的细节。它建立在 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/db/models/\"><span class=\"doc\">模型</span></a> 和 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/db/queries/\"><span class=\"doc\">数据库查询</span></a> 指南中所介绍的材料基础上，因此，在阅读本文档之前，你可能需要阅读并理解这些文档。</p>\n<p>在整个参考资料中，我们将使用在 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/db/queries/\"><span class=\"doc\">数据库查询指南</span></a> 中提出的  <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/db/queries/#queryset-model-example\"><span class=\"std std-ref\">示例博客模型</span></a>。</p>\n<section id=\"creating-objects\">\n<h2>创建对象<a class=\"heading-anchor\" href=\"#creating-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>要创建一个新的模型实例，像其他 Python 类一样实例化它。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model\">\n<em class=\"property\"><span class=\"k\">class</span> </em><span class=\"sig-name descname\">Model</span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\">**</span>kwargs</em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>关键字参数是你在模型上定义的字段名。请注意，实例化一个模型不会触及你的数据库；为此，你需要 <a class=\"reference internal\" href=\"#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\">save()</code></a>。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>你可能会想通过覆盖 <code class=\"docutils literal notranslate\">__init__</code> 方法来定制模型。但是，如果你这样做，请注意不要更改调用签名，因为任何更改都可能阻止模型实例被保存。与其覆盖 <code class=\"docutils literal notranslate\">__init__</code>，不如尝试使用以下方法之一：</p>\n<ol class=\"arabic\">\n<li><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\">django.db</span> <span class=\"kn\">import</span> models\n\n<span class=\"k\">class</span> <span class=\"nc\">Book</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    title <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n\n    <span class=\"nd\">@classmethod</span>\n    <span class=\"k\">def</span> <span class=\"nf\">create</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">,</span> title<span class=\"p\">):</span>\n        book <span class=\"o\">=</span> <span class=\"bp\">cls</span><span class=\"p\">(</span>title<span class=\"o\">=</span>title<span class=\"p\">)</span>\n        <span class=\"c1\"># do something with the book</span>\n        <span class=\"k\">return</span> book\n\nbook <span class=\"o\">=</span> Book<span class=\"o\">.</span>create<span class=\"p\">(</span><span class=\"s2\">&quot;Pride and Prejudice&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</li>\n<li><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=\"k\">class</span> <span class=\"nc\">BookManager</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Manager<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">create_book</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> title<span class=\"p\">):</span>\n        book <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>create<span class=\"p\">(</span>title<span class=\"o\">=</span>title<span class=\"p\">)</span>\n        <span class=\"c1\"># do something with the book</span>\n        <span class=\"k\">return</span> book\n\n<span class=\"k\">class</span> <span class=\"nc\">Book</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    title <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n\n    objects <span class=\"o\">=</span> BookManager<span class=\"p\">()</span>\n\nbook <span class=\"o\">=</span> Book<span class=\"o\">.</span>objects<span class=\"o\">.</span>create_book<span class=\"p\">(</span><span class=\"s2\">&quot;Pride and Prejudice&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</li>\n</ol>\n</aside>\n<section id=\"customizing-model-loading\">\n<h3>自定义模型加载<a class=\"heading-anchor\" href=\"#customizing-model-loading\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.from_db\">\n<em class=\"property\"><span class=\"k\">classmethod</span> </em><span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">from_db</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">db</em>, <em class=\"sig-param\">field_names</em>, <em class=\"sig-param\">values</em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.from_db\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\">from_db()</code> 方法可以在数据库加载时用于自定义模型实例创建。</p>\n<p><code class=\"docutils literal notranslate\">db</code> 参数包含模型从数据库加载的数据库别名，<code class=\"docutils literal notranslate\">field_names</code> 包含所有加载字段的名称，<code class=\"docutils literal notranslate\">values</code> 包含 <code class=\"docutils literal notranslate\">field_names</code> 中每个字段的加载值。<code class=\"docutils literal notranslate\">field_names</code> 和 <code class=\"docutils literal notranslate\">values</code> 的顺序相同。如果模型的所有字段都存在，那么 <code class=\"docutils literal notranslate\">values</code> 就必须按照 <code class=\"docutils literal notranslate\">__init__()</code> 预期的顺序。也就是说，实例可以通过 <code class=\"docutils literal notranslate\">cls(*values)</code> 来创建。如果有任何字段被推迟，它们将不会出现在 <code class=\"docutils literal notranslate\">field_names</code> 中。在这种情况下，给每个缺失的字段分配一个 <code class=\"docutils literal notranslate\">django.db.models.DEFERRED</code> 的值。</p>\n<p>除了创建新的模型外，<code class=\"docutils literal notranslate\">from_db()</code> 方法必须在新实例的 <a class=\"reference internal\" href=\"#django.db.models.Model._state\" title=\"django.db.models.Model._state\"><code class=\"xref py py-attr docutils literal notranslate\">_state</code></a> 属性中设置 <code class=\"docutils literal notranslate\">adding</code> 和 <code class=\"docutils literal notranslate\">db</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\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> DEFERRED\n\n<span class=\"nd\">@classmethod</span>\n<span class=\"k\">def</span> <span class=\"nf\">from_db</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">,</span> db<span class=\"p\">,</span> field_names<span class=\"p\">,</span> values<span class=\"p\">):</span>\n    <span class=\"c1\"># Default implementation of from_db() (subject to change and could</span>\n    <span class=\"c1\"># be replaced with super()).</span>\n    <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span>values<span class=\"p\">)</span> <span class=\"o\">!=</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"o\">.</span>_meta<span class=\"o\">.</span>concrete_fields<span class=\"p\">):</span>\n        values <span class=\"o\">=</span> <span class=\"nb\">list</span><span class=\"p\">(</span>values<span class=\"p\">)</span>\n        values<span class=\"o\">.</span>reverse<span class=\"p\">()</span>\n        values <span class=\"o\">=</span> <span class=\"p\">[</span>\n            values<span class=\"o\">.</span>pop<span class=\"p\">()</span> <span class=\"k\">if</span> f<span class=\"o\">.</span>attname <span class=\"ow\">in</span> field_names <span class=\"k\">else</span> DEFERRED\n            <span class=\"k\">for</span> f <span class=\"ow\">in</span> <span class=\"bp\">cls</span><span class=\"o\">.</span>_meta<span class=\"o\">.</span>concrete_fields\n        <span class=\"p\">]</span>\n    instance <span class=\"o\">=</span> <span class=\"bp\">cls</span><span class=\"p\">(</span><span class=\"o\">*</span>values<span class=\"p\">)</span>\n    instance<span class=\"o\">.</span>_state<span class=\"o\">.</span>adding <span class=\"o\">=</span> <span class=\"kc\">False</span>\n    instance<span class=\"o\">.</span>_state<span class=\"o\">.</span>db <span class=\"o\">=</span> db\n    <span class=\"c1\"># customization to store the original field values on the instance</span>\n    instance<span class=\"o\">.</span>_loaded_values <span class=\"o\">=</span> <span class=\"nb\">dict</span><span class=\"p\">(</span>\n        <span class=\"nb\">zip</span><span class=\"p\">(</span>field_names<span class=\"p\">,</span> <span class=\"p\">(</span>value <span class=\"k\">for</span> value <span class=\"ow\">in</span> values <span class=\"k\">if</span> value <span class=\"ow\">is</span> <span class=\"ow\">not</span> DEFERRED<span class=\"p\">))</span>\n    <span class=\"p\">)</span>\n    <span class=\"k\">return</span> instance\n\n<span class=\"k\">def</span> <span class=\"nf\">save</span><span class=\"p\">(</span><span class=\"bp\">self</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=\"c1\"># Check how the current values differ from ._loaded_values. For example,</span>\n    <span class=\"c1\"># prevent changing the creator_id of the model. (This example doesn&#39;t</span>\n    <span class=\"c1\"># support cases where &#39;creator_id&#39; is deferred).</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"bp\">self</span><span class=\"o\">.</span>_state<span class=\"o\">.</span>adding <span class=\"ow\">and</span> <span class=\"p\">(</span>\n            <span class=\"bp\">self</span><span class=\"o\">.</span>creator_id <span class=\"o\">!=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>_loaded_values<span class=\"p\">[</span><span class=\"s1\">&#39;creator_id&#39;</span><span class=\"p\">]):</span>\n        <span class=\"k\">raise</span> <span class=\"ne\">ValueError</span><span class=\"p\">(</span><span class=\"s2\">&quot;Updating the value of creator isn&#39;t allowed&quot;</span><span class=\"p\">)</span>\n    <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>save<span class=\"p\">(</span><span class=\"o\">*</span>args<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">)</span>\n</code></pre></div>\n<p>上面的例子显示了一个完整的 <code class=\"docutils literal notranslate\">from_db()</code> 实现，以说明如何做到这一点。在这种情况下，可以在 <code class=\"docutils literal notranslate\">from_db()</code> 方法中使用 <code class=\"docutils literal notranslate\">super()</code> 调用。</p>\n</section>\n</section>\n<section id=\"refreshing-objects-from-database\">\n<h2>从数据库中刷新对象<a class=\"heading-anchor\" href=\"#refreshing-objects-from-database\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\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=\"gp\">&gt;&gt;&gt; </span>obj <span class=\"o\">=</span> MyModel<span class=\"o\">.</span>objects<span class=\"o\">.</span>first<span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">del</span> obj<span class=\"o\">.</span>field\n<span class=\"gp\">&gt;&gt;&gt; </span>obj<span class=\"o\">.</span>field  <span class=\"c1\"># Loads the field from the database</span>\n</code></pre></div>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.refresh_from_db\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">refresh_from_db</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">using<span class=\"o\">=</span><span class=\"default_value\">None</span></em>, <em class=\"sig-param\">fields<span class=\"o\">=</span><span class=\"default_value\">None</span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.refresh_from_db\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>如果你需要从数据库中重新加载一个模型的值，你可以使用 <code class=\"docutils literal notranslate\">refresh_from_db()</code> 方法。当这个方法被调用时，没有参数时，会做以下工作：</p>\n<ol class=\"arabic simple\">\n<li><p>模型的所有非递延字段都更新为数据库中当前的值。</p></li>\n<li><p>任何缓存的关系都会从重新加载的实例中清除。</p></li>\n</ol>\n<p>只有模型的字段会从数据库中重载。其他依赖于数据库的值，如注释，不会被重载。任何 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/utils/#django.utils.functional.cached_property\" title=\"django.utils.functional.cached_property\"><code class=\"xref py py-func docutils literal notranslate\">&#64;cached_property</code></a> 属性也不会被清除。</p>\n<p>重载发生在实例被加载的数据库中，如果实例不是从数据库中加载的，则从默认数据库中加载。<code class=\"docutils literal notranslate\">using</code> 参数可以用来强制使用数据库进行重载。</p>\n<p>可以通过使用 <code class=\"docutils literal notranslate\">fields</code> 参数强制加载一组字段。</p>\n<p>例如，为了测试 <code class=\"docutils literal notranslate\">update()</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\">def</span> <span class=\"nf\">test_update_result</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    obj <span class=\"o\">=</span> MyModel<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>val<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n    MyModel<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>pk<span class=\"o\">=</span>obj<span class=\"o\">.</span>pk<span class=\"p\">)</span><span class=\"o\">.</span>update<span class=\"p\">(</span>val<span class=\"o\">=</span>F<span class=\"p\">(</span><span class=\"s1\">&#39;val&#39;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n    <span class=\"c1\"># At this point obj.val is still 1, but the value in the database</span>\n    <span class=\"c1\"># was updated to 2. The object&#39;s updated value needs to be reloaded</span>\n    <span class=\"c1\"># from the database.</span>\n    obj<span class=\"o\">.</span>refresh_from_db<span class=\"p\">()</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span>assertEqual<span class=\"p\">(</span>obj<span class=\"o\">.</span>val<span class=\"p\">,</span> <span class=\"mi\">2</span><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=\"k\">class</span> <span class=\"nc\">ExampleModel</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    <span class=\"k\">def</span> <span class=\"nf\">refresh_from_db</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> using<span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> fields<span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">):</span>\n        <span class=\"c1\"># fields contains the name of the deferred field to be</span>\n        <span class=\"c1\"># loaded.</span>\n        <span class=\"k\">if</span> fields <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            fields <span class=\"o\">=</span> <span class=\"nb\">set</span><span class=\"p\">(</span>fields<span class=\"p\">)</span>\n            deferred_fields <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>get_deferred_fields<span class=\"p\">()</span>\n            <span class=\"c1\"># If any deferred field is going to be loaded</span>\n            <span class=\"k\">if</span> fields<span class=\"o\">.</span>intersection<span class=\"p\">(</span>deferred_fields<span class=\"p\">):</span>\n                <span class=\"c1\"># then load all of them</span>\n                fields <span class=\"o\">=</span> fields<span class=\"o\">.</span>union<span class=\"p\">(</span>deferred_fields<span class=\"p\">)</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>refresh_from_db<span class=\"p\">(</span>using<span class=\"p\">,</span> fields<span class=\"p\">,</span> <span class=\"o\">**</span>kwargs<span class=\"p\">)</span>\n</code></pre></div>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.get_deferred_fields\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">get_deferred_fields</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.get_deferred_fields\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>一个辅助方法，返回一个包含当前这个模型的所有这些字段的属性名的集合。</p>\n</section>\n<section id=\"validating-objects\">\n<span id=\"id1\"></span><h2>验证对象<a class=\"heading-anchor\" href=\"#validating-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>There are four steps involved in validating a model:</p>\n<ol class=\"arabic simple\">\n<li><p>验证模型字段—— <a class=\"reference internal\" href=\"#django.db.models.Model.clean_fields\" title=\"django.db.models.Model.clean_fields\"><code class=\"xref py py-meth docutils literal notranslate\">Model.clean_fields()</code></a></p></li>\n<li><p>验证整个模型—— <a class=\"reference internal\" href=\"#django.db.models.Model.clean\" title=\"django.db.models.Model.clean\"><code class=\"xref py py-meth docutils literal notranslate\">Model.clean()</code></a></p></li>\n<li><p>验证字段的唯一性—— <a class=\"reference internal\" href=\"#django.db.models.Model.validate_unique\" title=\"django.db.models.Model.validate_unique\"><code class=\"xref py py-meth docutils literal notranslate\">Model.validate_unique()</code></a></p></li>\n<li><p>Validate the constraints - <a class=\"reference internal\" href=\"#django.db.models.Model.validate_constraints\" title=\"django.db.models.Model.validate_constraints\"><code class=\"xref py py-meth docutils literal notranslate\">Model.validate_constraints()</code></a></p></li>\n</ol>\n<p>All four steps are performed when you call a model's <a class=\"reference internal\" href=\"#django.db.models.Model.full_clean\" title=\"django.db.models.Model.full_clean\"><code class=\"xref py py-meth docutils literal notranslate\">full_clean()</code></a>\nmethod.</p>\n<p>当你使用一个 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/forms/modelforms/#django.forms.ModelForm\" title=\"django.forms.ModelForm\"><code class=\"xref py py-class docutils literal notranslate\">ModelForm</code></a> 时，调用 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/forms/api/#django.forms.Form.is_valid\" title=\"django.forms.Form.is_valid\"><code class=\"xref py py-meth docutils literal notranslate\">is_valid()</code></a> 将对表单中包含的所有字段执行这些验证步骤。更多信息请参见 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/forms/modelforms/\"><span class=\"doc\">模型表单文档</span></a>。只有当你打算自己处理验证错误，或者你从 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/forms/modelforms/#django.forms.ModelForm\" title=\"django.forms.ModelForm\"><code class=\"xref py py-class docutils literal notranslate\">ModelForm</code></a> 中排除了需要验证的字段时，才需要调用模型的 <a class=\"reference internal\" href=\"#django.db.models.Model.full_clean\" title=\"django.db.models.Model.full_clean\"><code class=\"xref py py-meth docutils literal notranslate\">full_clean()</code></a> 方法。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>Constraints containing <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.JSONField\" title=\"django.db.models.JSONField\"><code class=\"xref py py-class docutils literal notranslate\">JSONField</code></a> may not raise\nvalidation errors as key, index, and path transforms have many\ndatabase-specific caveats. This <a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/34059\">may be fully supported later</a>.</p>\n<p>You should always check that there are no log messages, in the\n<code class=\"docutils literal notranslate\">django.db.models</code> logger, like <em>&quot;Got a database error calling check() on\n…&quot;</em> to confirm it's validated properly.</p>\n</aside>\n<aside class=\"version-note version-changed\" data-version=\"4.1\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 4.1</p><p>In older versions, constraints were not checked during the model\nvalidation.</p>\n</aside>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.full_clean\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">full_clean</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">exclude<span class=\"o\">=</span><span class=\"default_value\">None</span></em>, <em class=\"sig-param\">validate_unique<span class=\"o\">=</span><span class=\"default_value\">True</span></em>, <em class=\"sig-param\">validate_constraints<span class=\"o\">=</span><span class=\"default_value\">True</span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.full_clean\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>This method calls <a class=\"reference internal\" href=\"#django.db.models.Model.clean_fields\" title=\"django.db.models.Model.clean_fields\"><code class=\"xref py py-meth docutils literal notranslate\">Model.clean_fields()</code></a>, <a class=\"reference internal\" href=\"#django.db.models.Model.clean\" title=\"django.db.models.Model.clean\"><code class=\"xref py py-meth docutils literal notranslate\">Model.clean()</code></a>,\n<a class=\"reference internal\" href=\"#django.db.models.Model.validate_unique\" title=\"django.db.models.Model.validate_unique\"><code class=\"xref py py-meth docutils literal notranslate\">Model.validate_unique()</code></a> (if <code class=\"docutils literal notranslate\">validate_unique</code> is <code class=\"docutils literal notranslate\">True</code>),  and\n<a class=\"reference internal\" href=\"#django.db.models.Model.validate_constraints\" title=\"django.db.models.Model.validate_constraints\"><code class=\"xref py py-meth docutils literal notranslate\">Model.validate_constraints()</code></a> (if <code class=\"docutils literal notranslate\">validate_constraints</code> is <code class=\"docutils literal notranslate\">True</code>)\nin that order and raises a <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\">ValidationError</code></a> that\nhas a <code class=\"docutils literal notranslate\">message_dict</code> attribute containing errors from all four stages.</p>\n<p>The optional <code class=\"docutils literal notranslate\">exclude</code> argument can be used to provide a <code class=\"docutils literal notranslate\">set</code> of field\nnames that can be excluded from validation and cleaning.\n<a class=\"reference internal\" href=\"/zh-hans/4.1/topics/forms/modelforms/#django.forms.ModelForm\" title=\"django.forms.ModelForm\"><code class=\"xref py py-class docutils literal notranslate\">ModelForm</code></a> uses this argument to exclude fields that\naren't present on your form from being validated since any errors raised could\nnot be corrected by the user.</p>\n<p>请注意，当您调用模型的 <a class=\"reference internal\" href=\"#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\">save()</code></a> 方法时，<code class=\"docutils literal notranslate\">full_clean()</code> <em>不会</em> 自动调用。当你想为自己手动创建的模型运行一步模型验证时，你需要手动调用它。例如：</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.core.exceptions</span> <span class=\"kn\">import</span> ValidationError\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    article<span class=\"o\">.</span>full_clean<span class=\"p\">()</span>\n<span class=\"k\">except</span> ValidationError <span class=\"k\">as</span> e<span class=\"p\">:</span>\n    <span class=\"c1\"># Do something based on the errors contained in e.message_dict.</span>\n    <span class=\"c1\"># Display them to a user, or handle them programmatically.</span>\n    <span class=\"k\">pass</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">full_clean()</code> 执行的第一步是清理每个单独的字段。</p>\n<aside class=\"version-note version-changed\" data-version=\"4.1\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 4.1</p><p>The <code class=\"docutils literal notranslate\">validate_constraints</code> argument was added.</p>\n</aside>\n<aside class=\"version-note version-changed\" data-version=\"4.1\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 4.1</p><p>An <code class=\"docutils literal notranslate\">exclude</code> value is now converted to a <code class=\"docutils literal notranslate\">set</code> rather than a <code class=\"docutils literal notranslate\">list</code>.</p>\n</aside>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.clean_fields\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">clean_fields</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">exclude<span class=\"o\">=</span><span class=\"default_value\">None</span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.clean_fields\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>This method will validate all fields on your model. The optional <code class=\"docutils literal notranslate\">exclude</code>\nargument lets you provide a <code class=\"docutils literal notranslate\">set</code> of field names to exclude from validation.\nIt will raise a <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\">ValidationError</code></a> if any fields\nfail validation.</p>\n<p><code class=\"docutils literal notranslate\">full_clean()</code> 执行的第二步是调用 <a class=\"reference internal\" href=\"#django.db.models.Model.clean\" title=\"django.db.models.Model.clean\"><code class=\"xref py py-meth docutils literal notranslate\">Model.clean()</code></a>。这个方法应该被重写，以便对你的模型进行自定义验证。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.clean\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">clean</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.clean\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\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=\"nn\">datetime</span>\n<span class=\"kn\">from</span> <span class=\"nn\">django.core.exceptions</span> <span class=\"kn\">import</span> ValidationError\n<span class=\"kn\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n<span class=\"kn\">from</span> <span class=\"nn\">django.utils.translation</span> <span class=\"kn\">import</span> gettext_lazy <span class=\"k\">as</span> _\n\n<span class=\"k\">class</span> <span class=\"nc\">Article</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n    <span class=\"k\">def</span> <span class=\"nf\">clean</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Don&#39;t allow draft entries to have a pub_date.</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span>status <span class=\"o\">==</span> <span class=\"s1\">&#39;draft&#39;</span> <span class=\"ow\">and</span> <span class=\"bp\">self</span><span class=\"o\">.</span>pub_date <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> ValidationError<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s1\">&#39;Draft entries may not have a publication date.&#39;</span><span class=\"p\">))</span>\n        <span class=\"c1\"># Set the pub_date for published items if it hasn&#39;t been set already.</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span>status <span class=\"o\">==</span> <span class=\"s1\">&#39;published&#39;</span> <span class=\"ow\">and</span> <span class=\"bp\">self</span><span class=\"o\">.</span>pub_date <span class=\"ow\">is</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            <span class=\"bp\">self</span><span class=\"o\">.</span>pub_date <span class=\"o\">=</span> datetime<span class=\"o\">.</span>date<span class=\"o\">.</span>today<span class=\"p\">()</span>\n</code></pre></div>\n<p>但请注意，像 <a class=\"reference internal\" href=\"#django.db.models.Model.full_clean\" title=\"django.db.models.Model.full_clean\"><code class=\"xref py py-meth docutils literal notranslate\">Model.full_clean()</code></a> 一样，当你调用你的模型的 <a class=\"reference internal\" href=\"#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\">save()</code></a> 方法时，模型的 <code class=\"docutils literal notranslate\">clean()</code> 方法不会被调用。</p>\n<p>在上面的例子中，由 <code class=\"docutils literal notranslate\">Model.clean()</code> 引发的 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\">ValidationError</code></a> 异常是用字符串实例化的，所以它将被存储在一个特殊的错误字典键中， <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/exceptions/#django.core.exceptions.NON_FIELD_ERRORS\" title=\"django.core.exceptions.NON_FIELD_ERRORS\"><code class=\"xref py py-data docutils literal notranslate\">NON_FIELD_ERRORS</code></a>。这个键用于与整个模型相关的错误，而不是与某个特定字段相关的错误：</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.core.exceptions</span> <span class=\"kn\">import</span> NON_FIELD_ERRORS<span class=\"p\">,</span> ValidationError\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    article<span class=\"o\">.</span>full_clean<span class=\"p\">()</span>\n<span class=\"k\">except</span> ValidationError <span class=\"k\">as</span> e<span class=\"p\">:</span>\n    non_field_errors <span class=\"o\">=</span> e<span class=\"o\">.</span>message_dict<span class=\"p\">[</span>NON_FIELD_ERRORS<span class=\"p\">]</span>\n</code></pre></div>\n<p>要将异常分配给一个特定的字段，用一个字典实例化 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\">ValidationError</code></a>，其中键是字段名。我们可以更新前面的例子，将错误分配给 <code class=\"docutils literal notranslate\">pub_date</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=\"nc\">Article</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n    <span class=\"k\">def</span> <span class=\"nf\">clean</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Don&#39;t allow draft entries to have a pub_date.</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span>status <span class=\"o\">==</span> <span class=\"s1\">&#39;draft&#39;</span> <span class=\"ow\">and</span> <span class=\"bp\">self</span><span class=\"o\">.</span>pub_date <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> ValidationError<span class=\"p\">({</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">:</span> _<span class=\"p\">(</span><span class=\"s1\">&#39;Draft entries may not have a publication date.&#39;</span><span class=\"p\">)})</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n<p>如果你在 <code class=\"docutils literal notranslate\">Model.clean()</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\">raise</span> ValidationError<span class=\"p\">({</span>\n    <span class=\"s1\">&#39;title&#39;</span><span class=\"p\">:</span> ValidationError<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s1\">&#39;Missing title.&#39;</span><span class=\"p\">),</span> code<span class=\"o\">=</span><span class=\"s1\">&#39;required&#39;</span><span class=\"p\">),</span>\n    <span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">:</span> ValidationError<span class=\"p\">(</span>_<span class=\"p\">(</span><span class=\"s1\">&#39;Invalid date.&#39;</span><span class=\"p\">),</span> code<span class=\"o\">=</span><span class=\"s1\">&#39;invalid&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">})</span>\n</code></pre></div>\n<p>Then, <code class=\"docutils literal notranslate\">full_clean()</code> will check unique constraints on your model.</p>\n<aside class=\"admonition-how-to-raise-field-specific-validation-errors-if-those-fields-don-t-appear-in-a-modelform admonition\" role=\"note\">\n<p class=\"admonition-title\">如果字段没有出现在 <code class=\"docutils literal notranslate\">ModelForm</code> 中，如何引发特定字段的验证错误。</p>\n<p>你不能在 <code class=\"docutils literal notranslate\">Model.clean()</code> 中对没有出现在模型表单中的字段提出验证错误（一个表单可以使用 <code class=\"docutils literal notranslate\">Meta.field</code> 或 <code class=\"docutils literal notranslate\">Meta.exclude</code> 来限制它的字段）。这样做会引发一个 <code class=\"docutils literal notranslate\">ValueError</code>，因为验证错误将无法与被排除的字段相关联。</p>\n<p>为了解决这个难题，可以覆盖 <a class=\"reference internal\" href=\"#django.db.models.Model.clean_fields\" title=\"django.db.models.Model.clean_fields\"><code class=\"xref py py-meth docutils literal notranslate\">Model.clean_fields()</code></a>，因为它接收的是被排除在验证之外的字段列表。例如：</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=\"nc\">Article</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n    <span class=\"k\">def</span> <span class=\"nf\">clean_fields</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> exclude<span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span>clean_fields<span class=\"p\">(</span>exclude<span class=\"o\">=</span>exclude<span class=\"p\">)</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span>status <span class=\"o\">==</span> <span class=\"s1\">&#39;draft&#39;</span> <span class=\"ow\">and</span> <span class=\"bp\">self</span><span class=\"o\">.</span>pub_date <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            <span class=\"k\">if</span> exclude <span class=\"ow\">and</span> <span class=\"s1\">&#39;status&#39;</span> <span class=\"ow\">in</span> exclude<span class=\"p\">:</span>\n                <span class=\"k\">raise</span> ValidationError<span class=\"p\">(</span>\n                    _<span class=\"p\">(</span><span class=\"s1\">&#39;Draft entries may not have a publication date.&#39;</span><span class=\"p\">)</span>\n                <span class=\"p\">)</span>\n            <span class=\"k\">else</span><span class=\"p\">:</span>\n                <span class=\"k\">raise</span> ValidationError<span class=\"p\">({</span>\n                    <span class=\"s1\">&#39;status&#39;</span><span class=\"p\">:</span> _<span class=\"p\">(</span>\n                        <span class=\"s1\">&#39;Set status to draft if there is not a &#39;</span>\n                        <span class=\"s1\">&#39;publication date.&#39;</span>\n                     <span class=\"p\">),</span>\n                <span class=\"p\">})</span>\n</code></pre></div>\n</aside>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.validate_unique\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">validate_unique</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">exclude<span class=\"o\">=</span><span class=\"default_value\">None</span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.validate_unique\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>This method is similar to <a class=\"reference internal\" href=\"#django.db.models.Model.clean_fields\" title=\"django.db.models.Model.clean_fields\"><code class=\"xref py py-meth docutils literal notranslate\">clean_fields()</code></a>, but validates\nuniqueness constraints defined via <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.Field.unique\" title=\"django.db.models.Field.unique\"><code class=\"xref py py-attr docutils literal notranslate\">Field.unique</code></a>,\n<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.Field.unique_for_date\" title=\"django.db.models.Field.unique_for_date\"><code class=\"xref py py-attr docutils literal notranslate\">Field.unique_for_date</code></a>, <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.Field.unique_for_month\" title=\"django.db.models.Field.unique_for_month\"><code class=\"xref py py-attr docutils literal notranslate\">Field.unique_for_month</code></a>,\n<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.Field.unique_for_year\" title=\"django.db.models.Field.unique_for_year\"><code class=\"xref py py-attr docutils literal notranslate\">Field.unique_for_year</code></a>, or <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/options/#django.db.models.Options.unique_together\" title=\"django.db.models.Options.unique_together\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.unique_together</code></a> on your model instead of individual\nfield values. The optional <code class=\"docutils literal notranslate\">exclude</code> argument allows you to provide a <code class=\"docutils literal notranslate\">set</code>\nof field names to exclude from validation. It will raise a\n<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\">ValidationError</code></a> if any fields fail validation.</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/constraints/#django.db.models.UniqueConstraint\" title=\"django.db.models.UniqueConstraint\"><code class=\"xref py py-class docutils literal notranslate\">UniqueConstraint</code></a>s defined in the\n<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/options/#django.db.models.Options.constraints\" title=\"django.db.models.Options.constraints\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.constraints</code></a> are validated\nby <a class=\"reference internal\" href=\"#django.db.models.Model.validate_constraints\" title=\"django.db.models.Model.validate_constraints\"><code class=\"xref py py-meth docutils literal notranslate\">Model.validate_constraints()</code></a>.</p>\n<p>请注意，如果你为 <code class=\"docutils literal notranslate\">validate_unique()</code> 提供了一个 <code class=\"docutils literal notranslate\">exclude</code> 参数，任何涉及你提供的一个字段的 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/options/#django.db.models.Options.unique_together\" title=\"django.db.models.Options.unique_together\"><code class=\"xref py py-attr docutils literal notranslate\">unique_together</code></a> 约束将不会被检查。</p>\n<p>Finally, <code class=\"docutils literal notranslate\">full_clean()</code> will check any other constraints on your model.</p>\n<aside class=\"version-note version-changed\" data-version=\"4.1\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 4.1</p><p>In older versions, <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/constraints/#django.db.models.UniqueConstraint\" title=\"django.db.models.UniqueConstraint\"><code class=\"xref py py-class docutils literal notranslate\">UniqueConstraint</code></a>s were\nvalidated by <code class=\"docutils literal notranslate\">validate_unique()</code>.</p>\n</aside>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.validate_constraints\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">validate_constraints</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">exclude<span class=\"o\">=</span><span class=\"default_value\">None</span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.validate_constraints\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<aside class=\"version-note version-added\" data-version=\"4.1\" role=\"note\">\n<p class=\"version-note-title\">New in Django 4.1</p></aside>\n<p>This method validates all constraints defined in\n<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/options/#django.db.models.Options.constraints\" title=\"django.db.models.Options.constraints\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.constraints</code></a>. The\noptional <code class=\"docutils literal notranslate\">exclude</code> argument allows you to provide a <code class=\"docutils literal notranslate\">set</code> of field names to\nexclude from validation. It will raise a\n<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\">ValidationError</code></a> if any constraints fail\nvalidation.</p>\n</section>\n<section id=\"saving-objects\">\n<h2>保存对象<a class=\"heading-anchor\" href=\"#saving-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>要将对象保存回数据库，调用 <code class=\"docutils literal notranslate\">save()</code>：</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.save\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">save</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">force_insert<span class=\"o\">=</span><span class=\"default_value\">False</span></em>, <em class=\"sig-param\">force_update<span class=\"o\">=</span><span class=\"default_value\">False</span></em>, <em class=\"sig-param\">using<span class=\"o\">=</span><span class=\"default_value\">DEFAULT_DB_ALIAS</span></em>, <em class=\"sig-param\">update_fields<span class=\"o\">=</span><span class=\"default_value\">None</span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.save\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>关于使用 <code class=\"docutils literal notranslate\">force_insert</code> 和 <code class=\"docutils literal notranslate\">force_update</code> 参数的细节，见 <a class=\"reference internal\" href=\"#ref-models-force-insert\"><span class=\"std std-ref\">强制执行 INSERT 或 UPDATE</span></a> 。关于 <code class=\"docutils literal notranslate\">update_fields</code> 参数的细节可以在 <a class=\"reference internal\" href=\"#ref-models-update-fields\"><span class=\"std std-ref\">指定要保存的字段</span></a> 部分找到。</p>\n<p>如果你想自定义保存行为，你可以覆盖这个 <code class=\"docutils literal notranslate\">save()</code> 方法。更多细节请参见 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/db/models/#overriding-model-methods\"><span class=\"std std-ref\">重写之前定义的模型方法</span></a>。</p>\n<p>模型保存过程也有一些微妙的地方，请看下面的章节。</p>\n<section id=\"auto-incrementing-primary-keys\">\n<h3>自增主键<a class=\"heading-anchor\" href=\"#auto-incrementing-primary-keys\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果一个模型有一个 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.AutoField\" title=\"django.db.models.AutoField\"><code class=\"xref py py-class docutils literal notranslate\">AutoField</code></a>——一个自动递增的主键，那么当你第一次调用 <code class=\"docutils literal notranslate\">save()</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=\"gp\">&gt;&gt;&gt; </span>b2 <span class=\"o\">=</span> Blog<span class=\"p\">(</span>name<span class=\"o\">=</span><span class=\"s1\">&#39;Cheddar Talk&#39;</span><span class=\"p\">,</span> tagline<span class=\"o\">=</span><span class=\"s1\">&#39;Thoughts on cheese.&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>b2<span class=\"o\">.</span>id     <span class=\"c1\"># Returns None, because b2 doesn&#39;t have an ID yet.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>b2<span class=\"o\">.</span>save<span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>b2<span class=\"o\">.</span>id     <span class=\"c1\"># Returns the ID of your new object.</span>\n</code></pre></div>\n<p>在你调用 <code class=\"docutils literal notranslate\">save()</code> 之前，没有办法知道一个 ID 的值是多少，因为这个值是由你的数据库计算出来的，而不是由 Django 计算出来的。</p>\n<p>为了方便起见，每个模型都有一个 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.AutoField\" title=\"django.db.models.AutoField\"><code class=\"xref py py-class docutils literal notranslate\">AutoField</code></a> 默认命名为 <code class=\"docutils literal notranslate\">id</code>，除非你在模型中的字段上明确指定 <code class=\"docutils literal notranslate\">primary_key=True</code>。更多细节请参见 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.AutoField\" title=\"django.db.models.AutoField\"><code class=\"xref py py-class docutils literal notranslate\">AutoField</code></a> 的文档。</p>\n<section id=\"the-pk-property\">\n<h4><code class=\"docutils literal notranslate\">pk</code> 属性<a class=\"heading-anchor\" href=\"#the-pk-property\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.pk\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">pk</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.pk\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>无论你是自己定义一个主键字段，还是让 Django 为你提供一个主键字段，每个模型都会有一个叫做 <code class=\"docutils literal notranslate\">pk</code> 的属性。它的行为就像模型上的一个普通属性，但实际上是模型主键字段属性的别名。您可以像读取和设置任何其他属性一样读取和设置这个值，它将更新模型中的正确字段。</p>\n</section>\n<section id=\"explicitly-specifying-auto-primary-key-values\">\n<h4>明确指定自动主键值<a class=\"heading-anchor\" href=\"#explicitly-specifying-auto-primary-key-values\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>如果一个模型有一个 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.AutoField\" title=\"django.db.models.AutoField\"><code class=\"xref py py-class docutils literal notranslate\">AutoField</code></a>，但你想在保存时显式地定义一个新对象的 ID，就在保存前显式地定义它，而不是依赖 ID 的自动分配：</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=\"gp\">&gt;&gt;&gt; </span>b3 <span class=\"o\">=</span> Blog<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">3</span><span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;Cheddar Talk&#39;</span><span class=\"p\">,</span> tagline<span class=\"o\">=</span><span class=\"s1\">&#39;Thoughts on cheese.&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>b3<span class=\"o\">.</span>id     <span class=\"c1\"># Returns 3.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>b3<span class=\"o\">.</span>save<span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>b3<span class=\"o\">.</span>id     <span class=\"c1\"># Returns 3.</span>\n</code></pre></div>\n<p>如果你手动分配自动主键值，请确保不要使用一个已经存在的主键值！如果你创建一个新的对象，并使用一个已经存在于数据库中的显式主键值，Django 会认为你是在改变现有的记录，而不是创建一个新的记录。</p>\n<p>考虑到上面的 <code class=\"docutils literal notranslate\">'Cheddar Talk'</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>b4 <span class=\"o\">=</span> Blog<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">3</span><span class=\"p\">,</span> name<span class=\"o\">=</span><span class=\"s1\">&#39;Not Cheddar&#39;</span><span class=\"p\">,</span> tagline<span class=\"o\">=</span><span class=\"s1\">&#39;Anything but cheese.&#39;</span><span class=\"p\">)</span>\nb4<span class=\"o\">.</span>save<span class=\"p\">()</span>  <span class=\"c1\"># Overrides the previous blog with ID=3!</span>\n</code></pre></div>\n<p>发生这种情况的原因，请看下面 <a class=\"reference internal\" href=\"#how-django-knows-to-update-vs-insert\">How Django knows to UPDATE vs. INSERT</a> 。</p>\n<p>明确指定自动主键值主要用于批量保存对象，当你确信不会发生主键碰撞时。</p>\n<p>如果你使用的是 PostgreSQL，与主键相关的序列可能需要更新；参见 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/databases/#manually-specified-autoincrement-pk\"><span class=\"std std-ref\">手动指定自增主键的值。</span></a>。</p>\n</section>\n</section>\n<section id=\"what-happens-when-you-save\">\n<h3>保存时会发生什么？<a class=\"heading-anchor\" href=\"#what-happens-when-you-save\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>当你保存一个对象时，Django 会执行以下步骤：</p>\n<ol class=\"arabic\">\n<li><p><strong>发送一个预保存信号。</strong> <a class=\"reference internal\" href=\"/zh-hans/4.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> 信号被发送，允许任何监听该信号的函数做一些事情。</p></li>\n<li><p><strong>预处理数据。</strong> 每个字段的 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.Field.pre_save\" title=\"django.db.models.Field.pre_save\"><code class=\"xref py py-meth docutils literal notranslate\">pre_save()</code></a> 方法被调用来执行任何需要的自动数据修改。例如，日期／时间字段重写了 <code class=\"docutils literal notranslate\">pre_save()</code> 来实现 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.DateField.auto_now_add\" title=\"django.db.models.DateField.auto_now_add\"><code class=\"xref py py-attr docutils literal notranslate\">auto_now_add</code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.DateField.auto_now\" title=\"django.db.models.DateField.auto_now\"><code class=\"xref py py-attr docutils literal notranslate\">auto_now</code></a>。</p></li>\n<li><p><strong>为数据库准备数据。</strong> 要求每个字段的 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.Field.get_db_prep_save\" title=\"django.db.models.Field.get_db_prep_save\"><code class=\"xref py py-meth docutils literal notranslate\">get_db_prep_save()</code></a> 方法提供其当前的值，数据类型可以写入数据库。</p>\n<p>大多数字段不需要数据准备。简单的数据类型，如整数和字符串，作为一个 Python 对象是“可以写入”的。然而，更复杂的数据类型通常需要一些修改。</p>\n<p>例如，<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.DateField\" title=\"django.db.models.DateField\"><code class=\"xref py py-class docutils literal notranslate\">DateField</code></a> 字段使用 Python <code class=\"docutils literal notranslate\">datetime</code> 对象来存储数据。数据库不存储 <code class=\"docutils literal notranslate\">datetime</code> 对象，所以字段值必须转换成符合 ISO 标准的日期字符串才能插入数据库。</p>\n</li>\n<li><p><strong>将数据插入数据库。</strong> 将预先处理、准备好的数据组成 SQL 语句，以便插入数据库。</p></li>\n<li><p><strong>发送一个保存后的信号。</strong> <a class=\"reference internal\" href=\"/zh-hans/4.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> 信号被发送，允许任何监听该信号的函数做一些事情。</p></li>\n</ol>\n</section>\n<section id=\"how-django-knows-to-update-vs-insert\">\n<h3>Django 是如何知道 UPDATE 与 INSERT 的？<a class=\"heading-anchor\" href=\"#how-django-knows-to-update-vs-insert\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你可能已经注意到 Django 数据库对象使用相同的 <code class=\"docutils literal notranslate\">save()</code> 方法来创建和更改对象。Django 抽象了需要使用 <code class=\"docutils literal notranslate\">INSERT</code> 或 <code class=\"docutils literal notranslate\">UPDATE</code> 的 SQL 语句。具体来说，当你调用 <code class=\"docutils literal notranslate\">save()</code>，而对象的主键属性 <strong>没有</strong> 定义一个 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.Field.default\" title=\"django.db.models.Field.default\"><code class=\"xref py py-attr docutils literal notranslate\">default</code></a> 时，Django 会遵循这个算法。</p>\n<ul class=\"simple\">\n<li><p>如果对象的主键属性被设置为值为 <code class=\"docutils literal notranslate\">True</code> （即，一个不是 <code class=\"docutils literal notranslate\">None</code> 或空字符串的值），Django 会执行 <code class=\"docutils literal notranslate\">UPDATE</code>。</p></li>\n<li><p>如果对象的主键属性没有设置，或者 <code class=\"docutils literal notranslate\">UPDATE</code> 没有更新任何东西（例如主键被设置为数据库中不存在的值），Django 会执行 <code class=\"docutils literal notranslate\">INSERT</code>。</p></li>\n</ul>\n<p>如果对象的主键属性定义了一个 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.Field.default\" title=\"django.db.models.Field.default\"><code class=\"xref py py-attr docutils literal notranslate\">default</code></a>，那么如果它是一个现有的模型实例，并且主键被设置为数据库中存在的值，Django 就会执行一个 <code class=\"docutils literal notranslate\">UPDATE</code>。否则，Django 会执行一个 <code class=\"docutils literal notranslate\">INSERT</code>。</p>\n<p>这里的一个问题是，如果你不能保证主键值未被使用，那么在保存新对象时，你应该注意不要显式地指定一个主键值。关于这个细微的差别，请看上面的 <a class=\"reference internal\" href=\"#explicitly-specifying-auto-primary-key-values\">Explicitly specifying auto-primary-key values</a> 和下面的 <a class=\"reference internal\" href=\"#forcing-an-insert-or-update\">Forcing an INSERT or UPDATE</a> 。</p>\n<p>在 Django 1.5 和更早的版本中，当主键属性被设置时，Django 执行 <code class=\"docutils literal notranslate\">SELECT</code>。如果 <code class=\"docutils literal notranslate\">SELECT</code> 找到了一条记录，那么 Django 就会进行 <code class=\"docutils literal notranslate\">UPDATE</code>，否则就会进行 <code class=\"docutils literal notranslate\">INSERT</code>。老算法的结果是在 <code class=\"docutils literal notranslate\">UPDATE</code> 的情况下多了一个查询。在一些罕见的情况下，即使数据库中包含了一条对象主键值的记录，数据库也不会报告某行被更新。一个例子是 PostgreSQL 的 <code class=\"docutils literal notranslate\">ON UPDATE</code> 触发器，它返回 <code class=\"docutils literal notranslate\">NULL</code>。在这种情况下，可以通过将 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/options/#django.db.models.Options.select_on_save\" title=\"django.db.models.Options.select_on_save\"><code class=\"xref py py-attr docutils literal notranslate\">select_on_save</code></a> 选项设置为 <code class=\"docutils literal notranslate\">True</code> 来恢复到旧算法。</p>\n<section id=\"forcing-an-insert-or-update\">\n<span id=\"ref-models-force-insert\"></span><h4>强制执行 INSERT 或 UPDATE<a class=\"heading-anchor\" href=\"#forcing-an-insert-or-update\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>在一些罕见的情况下，有必要强制 <a class=\"reference internal\" href=\"#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\">save()</code></a> 方法执行 SQL <code class=\"docutils literal notranslate\">INSERT</code>，而不是回到 <code class=\"docutils literal notranslate\">UPDATE</code>。或者反过来说：如果可能的话，更新，但不插入新的记录。在这些情况下，你可以将 <code class=\"docutils literal notranslate\">force_insert=True</code> 或 <code class=\"docutils literal notranslate\">force_update=True</code> 参数传递给 <a class=\"reference internal\" href=\"#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\">save()</code></a> 方法。一起传递这两个参数是一个错误：你不能同时插入 <em>和</em> 更新！</p>\n<p>你应该很少需要使用这些参数。Django 几乎总是会做正确的事情，试图覆盖会导致难以追踪的错误。这个功能只适合进阶使用。</p>\n<p>使用 <code class=\"docutils literal notranslate\">update_fields</code> 将强制更新，类似于 <code class=\"docutils literal notranslate\">force_update</code>。</p>\n</section>\n</section>\n<section id=\"updating-attributes-based-on-existing-fields\">\n<span id=\"ref-models-field-updates-using-f-expressions\"></span><h3>基于现有字段更新属性<a class=\"heading-anchor\" href=\"#updating-attributes-based-on-existing-fields\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>有时你需要在一个字段上执行一个简单的算术任务，比如递增或递减当前值。一种方法是在 Python 中进行运算，比如：</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=\"gp\">&gt;&gt;&gt; </span>product <span class=\"o\">=</span> Product<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>name<span class=\"o\">=</span><span class=\"s1\">&#39;Venezuelan Beaver Cheese&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>product<span class=\"o\">.</span>number_sold <span class=\"o\">+=</span> <span class=\"mi\">1</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>product<span class=\"o\">.</span>save<span class=\"p\">()</span>\n</code></pre></div>\n<p>如果从数据库中检索到的 <code class=\"docutils literal notranslate\">number_sold</code> 旧值是 10，那么 11 的值将被写回数据库。</p>\n<p>这个过程可以变得更健壮， <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/expressions/#avoiding-race-conditions-using-f\"><span class=\"std std-ref\">避免竞争条件</span></a>，以及通过表达相对于原始字段值的更新，而不是作为一个新值的显式赋值来稍微加快。Django 提供了 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/expressions/#django.db.models.F\" title=\"django.db.models.F\"><code class=\"xref py py-class docutils literal notranslate\">F 表达式</code></a> 来执行这种相对更新。使用 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/expressions/#django.db.models.F\" title=\"django.db.models.F\"><code class=\"xref py py-class docutils literal notranslate\">F 表达式</code></a>，前面的例子表示为：</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=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> F\n<span class=\"gp\">&gt;&gt;&gt; </span>product <span class=\"o\">=</span> Product<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>name<span class=\"o\">=</span><span class=\"s1\">&#39;Venezuelan Beaver Cheese&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>product<span class=\"o\">.</span>number_sold <span class=\"o\">=</span> F<span class=\"p\">(</span><span class=\"s1\">&#39;number_sold&#39;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"mi\">1</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>product<span class=\"o\">.</span>save<span class=\"p\">()</span>\n</code></pre></div>\n<p>更多细节，请参阅 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/expressions/#django.db.models.F\" title=\"django.db.models.F\"><code class=\"xref py py-class docutils literal notranslate\">F 表达式</code></a> 及其 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/db/queries/#topics-db-queries-update\"><span class=\"std std-ref\">在更新查询中的使用</span></a> 的文档。</p>\n</section>\n<section id=\"specifying-which-fields-to-save\">\n<span id=\"ref-models-update-fields\"></span><h3>指定要保存的字段<a class=\"heading-anchor\" href=\"#specifying-which-fields-to-save\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果 <code class=\"docutils literal notranslate\">save()</code> 在关键字参数 <code class=\"docutils literal notranslate\">update_fields</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>product<span class=\"o\">.</span>name <span class=\"o\">=</span> <span class=\"s1\">&#39;Name changed again&#39;</span>\nproduct<span class=\"o\">.</span>save<span class=\"p\">(</span>update_fields<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s1\">&#39;name&#39;</span><span class=\"p\">])</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">update_fields</code> 参数可以是任何包含字符串的可迭代对象。一个空的 <code class=\"docutils literal notranslate\">update_fields</code> 可迭代对象将跳过保存。值为 <code class=\"docutils literal notranslate\">None</code> 将对所有字段进行更新。</p>\n<p>指定 <code class=\"docutils literal notranslate\">update_fields</code> 将强制更新。</p>\n<p>当保存一个通过延迟模型加载获取的模型时（<code class=\"xref py py-meth docutils literal notranslate\">only()</code> 或 <code class=\"xref py py-meth docutils literal notranslate\">defer()</code>），只有从数据库加载的字段会被更新。实际上，在这种情况下有一个自动的 <code class=\"docutils literal notranslate\">update_fields</code>。如果你分配或改变任何延迟字段的值，该字段将被添加到更新的字段中。</p>\n<aside class=\"admonition-field-pre-save-and-update-fields admonition\" role=\"note\">\n<p class=\"admonition-title\"><code class=\"docutils literal notranslate\">Field.pre_save()</code> and <code class=\"docutils literal notranslate\">update_fields</code></p>\n<p>If <code class=\"docutils literal notranslate\">update_fields</code> is passed in, only the\n<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.Field.pre_save\" title=\"django.db.models.Field.pre_save\"><code class=\"xref py py-meth docutils literal notranslate\">pre_save()</code></a> methods of the <code class=\"docutils literal notranslate\">update_fields</code>\nare called. For example, this means that date/time fields with\n<code class=\"docutils literal notranslate\">auto_now=True</code> will not be updated unless they are included in the\n<code class=\"docutils literal notranslate\">update_fields</code>.</p>\n</aside>\n</section>\n</section>\n<section id=\"deleting-objects\">\n<h2>删除对象<a class=\"heading-anchor\" href=\"#deleting-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.delete\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">delete</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">using<span class=\"o\">=</span><span class=\"default_value\">DEFAULT_DB_ALIAS</span></em>, <em class=\"sig-param\">keep_parents<span class=\"o\">=</span><span class=\"default_value\">False</span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.delete\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Issues an SQL <code class=\"docutils literal notranslate\">DELETE</code> for the object. This only deletes the object in the\ndatabase; the Python instance will still exist and will still have data in\nits fields, except for the primary key set to <code class=\"docutils literal notranslate\">None</code>. This method returns the\nnumber of objects deleted and a dictionary with the number of deletions per\nobject type.</p>\n<p>更多细节，包括如何批量删除对象，请参见 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/db/queries/#topics-db-queries-delete\"><span class=\"std std-ref\">删除对象</span></a>。</p>\n<p>如果你想自定义删除行为，你可以覆盖 <code class=\"docutils literal notranslate\">delete()</code> 方法。更多细节请参见 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/db/models/#overriding-model-methods\"><span class=\"std std-ref\">重写之前定义的模型方法</span></a>。</p>\n<p>有时，在 <a class=\"reference internal\" href=\"/zh-hans/4.1/topics/db/models/#multi-table-inheritance\"><span class=\"std std-ref\">多表继承</span></a> 中，你可能只想删除子模型的数据，指定 <code class=\"docutils literal notranslate\">keep_parents=True</code> 将保留父模型的数据。指定 <code class=\"docutils literal notranslate\">keep_parents=True</code> 将保留父模型的数据。</p>\n</section>\n<section id=\"pickling-objects\">\n<h2>Pickle 序列化对象<a class=\"heading-anchor\" href=\"#pickling-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>当你 <a class=\"reference external\" href=\"https://docs.python.org/3/library/pickle.html#module-pickle\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\">pickle</code></a> 一个模型时，它的当前状态被序列化。当你反序列化时，它将包含它被序列化时的模型实例，而不是当前数据库中的数据。</p>\n<aside class=\"admonition-you-can-t-share-pickles-between-versions admonition\" role=\"note\">\n<p class=\"admonition-title\">你不能在不同版本之间共享 pickle</p>\n<p>模型的 pickle 只对生成它们的 Django 版本有效。如果你使用 Django 版本 N 生成了一个 pickle，那么不能保证这个 pickle 在 Django 版本 N+1 中可以被读取。Pickle 不应该作为长期存档策略的一部分。</p>\n<p>由于 pickle 兼容性错误可能很难诊断，比如静默损坏对象，所以当你试图在 Django 版本中反序列化模型时，会发出 <code class=\"docutils literal notranslate\">RuntimeWarning</code> 的警告。</p>\n</aside>\n</section>\n<section id=\"other-model-instance-methods\">\n<span id=\"model-instance-methods\"></span><h2>其他模型实例方法<a class=\"heading-anchor\" href=\"#other-model-instance-methods\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>有几个对象方法有特殊用途。</p>\n<section id=\"str\">\n<h3><code class=\"docutils literal notranslate\">__str__()</code><a class=\"heading-anchor\" href=\"#str\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.__str__\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">__str__</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.__str__\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>每当你对一个对象调用 <code class=\"docutils literal notranslate\">str()</code> 时，就会调用 <code class=\"docutils literal notranslate\">__str__()</code> 方法。Django 在很多地方使用了 <code class=\"docutils literal notranslate\">str(obj)</code> 方法。最主要的是，在 Django 管理站点中显示一个对象，以及作为模板显示对象时插入的值。因此，你应该总是从 <code class=\"docutils literal notranslate\">__str__()</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\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n\n<span class=\"k\">class</span> <span class=\"nc\">Person</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    first_name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">50</span><span class=\"p\">)</span>\n    last_name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">50</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span> <span class=\"fm\">__str__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\"> </span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span>first_name<span class=\"p\">,</span> <span class=\"bp\">self</span><span class=\"o\">.</span>last_name<span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"eq\">\n<h3><code class=\"docutils literal notranslate\">__eq__()</code><a class=\"heading-anchor\" href=\"#eq\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.__eq__\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">__eq__</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.__eq__\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>相等方法的定义是，具有相同主键值和相同具体类的实例被认为是相等的，但主键值为 <code class=\"docutils literal notranslate\">None</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\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n\n<span class=\"k\">class</span> <span class=\"nc\">MyModel</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    <span class=\"nb\">id</span> <span class=\"o\">=</span> models<span class=\"o\">.</span>AutoField<span class=\"p\">(</span>primary_key<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">MyProxyModel</span><span class=\"p\">(</span>MyModel<span class=\"p\">):</span>\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        proxy <span class=\"o\">=</span> <span class=\"kc\">True</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">MultitableInherited</span><span class=\"p\">(</span>MyModel<span class=\"p\">):</span>\n    <span class=\"k\">pass</span>\n\n<span class=\"c1\"># Primary keys compared</span>\nMyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span> <span class=\"o\">==</span> MyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\nMyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span> <span class=\"o\">!=</span> MyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">2</span><span class=\"p\">)</span>\n<span class=\"c1\"># Primary keys are None</span>\nMyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">)</span> <span class=\"o\">!=</span> MyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">)</span>\n<span class=\"c1\"># Same instance</span>\ninstance <span class=\"o\">=</span> MyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">)</span>\ninstance <span class=\"o\">==</span> instance\n<span class=\"c1\"># Proxy model</span>\nMyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span> <span class=\"o\">==</span> MyProxyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"c1\"># Multi-table inheritance</span>\nMyModel<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span> <span class=\"o\">!=</span> MultitableInherited<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"hash\">\n<h3><code class=\"docutils literal notranslate\">__hash__()</code><a class=\"heading-anchor\" href=\"#hash\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.__hash__\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">__hash__</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.__hash__\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\">__hash__()</code> 方法是基于实例的主键值。它实际上是 <code class=\"docutils literal notranslate\">hash(obj.pk)</code>。如果实例没有主键值，那么将引发一个 <code class=\"docutils literal notranslate\">TypeError</code> （否则 <code class=\"docutils literal notranslate\">__hash__()</code> 方法会在保存实例之前和之后返回不同的值，但是在 Python 中禁止改变实例的 <a class=\"reference external\" href=\"https://docs.python.org/3/reference/datamodel.html#object.__hash__\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\">__hash__()</code></a> 值。</p>\n</section>\n<section id=\"get-absolute-url\">\n<h3><code class=\"docutils literal notranslate\">get_absolute_url()</code><a class=\"heading-anchor\" href=\"#get-absolute-url\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.get_absolute_url\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">get_absolute_url</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.get_absolute_url\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>定义一个 <code class=\"docutils literal notranslate\">get_absolute_url()</code> 方法来告诉 Django 如何计算一个对象的标准 URL。对于调用者来说，这个方法应该返回一个字符串，可以通过 HTTP 引用对象。</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=\"k\">def</span> <span class=\"nf\">get_absolute_url</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"s2\">&quot;/people/</span><span class=\"si\">%i</span><span class=\"s2\">/&quot;</span> <span class=\"o\">%</span> <span class=\"bp\">self</span><span class=\"o\">.</span>id\n</code></pre></div>\n<p>虽然这段代码正确且简单，但它可能不是写这种方法的最可移植的方式。<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/urlresolvers/#django.urls.reverse\" title=\"django.urls.reverse\"><code class=\"xref py py-func docutils literal notranslate\">reverse()</code></a> 函数通常是最好的方法。</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=\"k\">def</span> <span class=\"nf\">get_absolute_url</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"kn\">from</span> <span class=\"nn\">django.urls</span> <span class=\"kn\">import</span> reverse\n    <span class=\"k\">return</span> reverse<span class=\"p\">(</span><span class=\"s1\">&#39;people-detail&#39;</span><span class=\"p\">,</span> kwargs<span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;pk&#39;</span> <span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span>pk<span class=\"p\">})</span>\n</code></pre></div>\n<p>Django 使用 <code class=\"docutils literal notranslate\">get_absolute_url()</code> 的一个地方就是在管理应用中。如果一个对象定义了这个方法，那么对象编辑页面会有一个“View on site”的链接，直接跳转到对象的公开视图，就像 <code class=\"docutils literal notranslate\">get_absolute_url()</code> 给出的那样。</p>\n<p>类似的，Django 的其他几个部分，比如 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/contrib/syndication/\"><span class=\"doc\">联合供稿框架</span></a>，当定义了 <code class=\"docutils literal notranslate\">get_absolute_url()</code> 时，也会使用 <code class=\"docutils literal notranslate\">get_absolute_url()</code>。如果你的模型的每个实例都有一个唯一的 URL，你应该定义 <code class=\"docutils literal notranslate\">get_absolute_url()</code>。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>你应该避免从未经验证的用户输入中建立 URL，以减少链接或重定向中毒的可能性：</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\">def</span> <span class=\"nf\">get_absolute_url</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"s1\">&#39;/</span><span class=\"si\">%s</span><span class=\"s1\">/&#39;</span> <span class=\"o\">%</span> <span class=\"bp\">self</span><span class=\"o\">.</span>name\n</code></pre></div>\n<p>如果 <code class=\"docutils literal notranslate\">self.name</code> 是 <code class=\"docutils literal notranslate\">'/example.com'</code>，这将返回 <code class=\"docutils literal notranslate\">'//example.com/'</code>，这反过来又是一个有效的协议相对 URL，但不是预期的 <code class=\"docutils literal notranslate\">'/%2Fexample.com/'</code>。</p>\n</aside>\n<p>在模板中使用 <code class=\"docutils literal notranslate\">get_absolute_url()</code>，而不是硬编码你的对象的 URL，这是一个很好的做法。例如，这个模板代码就很糟糕：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cm\">&lt;!-- BAD template code. Avoid! --&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;/people/</span><span class=\"cp\">{{</span> <span class=\"nv\">object.id</span> <span class=\"cp\">}}</span><span class=\"s\">/&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">object.name</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>这个模板代码就好多了：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">object.get_absolute_url</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">object.name</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>这里的逻辑是，如果你改变了你的对象的 URL 结构，即使是为了纠正拼写错误这样的小事，你也不想追踪 URL 可能被创建的每个地方。在 <code class=\"docutils literal notranslate\">get_absolute_url()</code> 中指定一次，然后让你的其他代码调用那个地方。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>从 <code class=\"docutils literal notranslate\">get_absolute_url()</code> 返回的字符串 <strong>必须</strong> 只包含 ASCII 字符（URI 规范要求，<span class=\"target\" id=\"index-2\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc2396.html#section-2\"><strong>RFC 2396 Section 2</strong></a>），并在必要时进行 URL 编码。</p>\n<p>调用 <code class=\"docutils literal notranslate\">get_absolute_url()</code> 的代码和模板应该可以直接使用结果，而不需要任何进一步的处理。如果你使用的字符串包含 ASCII 码范围以外的字符，你可能希望使用 <code class=\"docutils literal notranslate\">django.utils.encoding.iri_to_uri()</code> 函数来帮助解决这个问题。</p>\n</aside>\n</section>\n</section>\n<section id=\"extra-instance-methods\">\n<h2>额外的实例方法<a class=\"heading-anchor\" href=\"#extra-instance-methods\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>除了 <a class=\"reference internal\" href=\"#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\">save()</code></a>、 <a class=\"reference internal\" href=\"#django.db.models.Model.delete\" title=\"django.db.models.Model.delete\"><code class=\"xref py py-meth docutils literal notranslate\">delete()</code></a> 之外，一个模型对象还可能有以下一些方法：</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.get_FOO_display\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">get_FOO_display</span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.get_FOO_display\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>对于每一个设置了 <code class=\"xref py py-attr docutils literal notranslate\">choice</code> 的字段，该对象将有一个 <code class=\"docutils literal notranslate\">get_FOO_display()</code> 方法，其中 <code class=\"docutils literal notranslate\">FOO</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\">from</span> <span class=\"nn\">django.db</span> <span class=\"kn\">import</span> models\n\n<span class=\"k\">class</span> <span class=\"nc\">Person</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    SHIRT_SIZES <span class=\"o\">=</span> <span class=\"p\">(</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;S&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;Small&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;M&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;Medium&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;L&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;Large&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">)</span>\n    name <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">60</span><span class=\"p\">)</span>\n    shirt_size <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>max_length<span class=\"o\">=</span><span class=\"mi\">2</span><span class=\"p\">,</span> choices<span class=\"o\">=</span>SHIRT_SIZES<span class=\"p\">)</span>\n</code></pre></div>\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=\"gp\">&gt;&gt;&gt; </span>p <span class=\"o\">=</span> Person<span class=\"p\">(</span>name<span class=\"o\">=</span><span class=\"s2\">&quot;Fred Flintstone&quot;</span><span class=\"p\">,</span> shirt_size<span class=\"o\">=</span><span class=\"s2\">&quot;L&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>p<span class=\"o\">.</span>save<span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>p<span class=\"o\">.</span>shirt_size\n<span class=\"go\">&#39;L&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>p<span class=\"o\">.</span>get_shirt_size_display<span class=\"p\">()</span>\n<span class=\"go\">&#39;Large&#39;</span>\n</code></pre></div>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.get_next_by_FOO\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">get_next_by_FOO</span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\">**</span>kwargs</em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.get_next_by_FOO\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model.get_previous_by_FOO\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">get_previous_by_FOO</span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\">**</span>kwargs</em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Model.get_previous_by_FOO\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>对于每一个 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.DateField\" title=\"django.db.models.DateField\"><code class=\"xref py py-class docutils literal notranslate\">DateField</code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\">DateTimeField</code></a> 没有 <code class=\"xref py py-attr docutils literal notranslate\">null=True</code>，该对象将有 <code class=\"docutils literal notranslate\">get_next_by_FOO()</code> 和 <code class=\"docutils literal notranslate\">get_previous_by_FOO()</code> 方法，其中 <code class=\"docutils literal notranslate\">FOO</code> 是字段名。这将返回与日期字段相关的下一个和上一个对象，适当时引发一个 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/class/#django.db.models.Model.DoesNotExist\" title=\"django.db.models.Model.DoesNotExist\"><code class=\"xref py py-exc docutils literal notranslate\">DoesNotExist</code></a> 异常。</p>\n<p>这两种方法都将使用模型的默认管理器执行查询。如果你需要模拟自定义管理器使用的过滤，或者想要执行一次性的自定义过滤，这两种方法也都接受可选的关键字参数，其格式应该是 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/models/querysets/#field-lookups\"><span class=\"std std-ref\">字段查找</span></a> 中描述的格式。</p>\n<p>请注意，在日期值相同的情况下，这些方法将使用主键作为比较。这保证了没有记录被跳过或重复。这也意味着你不能对未保存的对象使用这些方法。</p>\n<aside class=\"admonition-overriding-extra-instance-methods admonition\" role=\"note\">\n<p class=\"admonition-title\">覆盖额外的实例方法</p>\n<p>在大多数情况下，覆盖或继承 <code class=\"docutils literal notranslate\">get_FOO_display()</code>、<code class=\"docutils literal notranslate\">get_next_by_FOO()</code> 和 <code class=\"docutils literal notranslate\">get_previous_by_FOO()</code> 应按预期工作。然而，由于它们是由元类添加的，所以要考虑所有可能的继承结构是不实际的。在更复杂的情况下，你应该覆盖 <code class=\"docutils literal notranslate\">Field.contribution_to_class()</code> 来设置你需要的方法。</p>\n</aside>\n</section>\n<section id=\"other-attributes\">\n<h2>其他属性<a class=\"heading-anchor\" href=\"#other-attributes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"state\">\n<h3><code class=\"docutils literal notranslate\">_state</code><a class=\"heading-anchor\" href=\"#state\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Model._state\">\n<span class=\"sig-prename descclassname\">Model.</span><span class=\"sig-name descname\">_state</span><a class=\"heading-anchor\" href=\"#django.db.models.Model._state\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><code class=\"docutils literal notranslate\">_state</code> 属性指的是一个 <code class=\"docutils literal notranslate\">ModelState</code> 对象，它跟踪模型实例的生命周期。</p>\n<p><code class=\"docutils literal notranslate\">ModelState</code> 对象有两个属性。<code class=\"docutils literal notranslate\">adding</code> 是一个标志，如果模型尚未保存到数据库，则为 <code class=\"docutils literal notranslate\">True</code>；<code class=\"docutils literal notranslate\">db</code> 是一个字符串，指的是实例从数据库加载或保存到的别名。</p>\n<p>新实例有 <code class=\"docutils literal notranslate\">adding=True</code> 和 <code class=\"docutils literal notranslate\">db=None</code>，因为它们尚未被保存。从 <code class=\"docutils literal notranslate\">QuerySet</code> 获取的实例将有 <code class=\"docutils literal notranslate\">adding=False</code> 和 <code class=\"docutils literal notranslate\">db</code> 设置为相关数据库的别名。</p>\n</dd></dl>\n\n</section>\n</section>","rootId":"model-instance-reference","toc":[{"title":"创建对象","anchor":"creating-objects","children":[{"title":"自定义模型加载","anchor":"customizing-model-loading","children":[]}]},{"title":"从数据库中刷新对象","anchor":"refreshing-objects-from-database","children":[]},{"title":"验证对象","anchor":"validating-objects","children":[]},{"title":"保存对象","anchor":"saving-objects","children":[{"title":"自增主键","anchor":"auto-incrementing-primary-keys","children":[{"title":"pk 属性","anchor":"the-pk-property","children":[]},{"title":"明确指定自动主键值","anchor":"explicitly-specifying-auto-primary-key-values","children":[]}]},{"title":"保存时会发生什么？","anchor":"what-happens-when-you-save","children":[]},{"title":"Django 是如何知道 UPDATE 与 INSERT 的？","anchor":"how-django-knows-to-update-vs-insert","children":[{"title":"强制执行 INSERT 或 UPDATE","anchor":"forcing-an-insert-or-update","children":[]}]},{"title":"基于现有字段更新属性","anchor":"updating-attributes-based-on-existing-fields","children":[]},{"title":"指定要保存的字段","anchor":"specifying-which-fields-to-save","children":[]}]},{"title":"删除对象","anchor":"deleting-objects","children":[]},{"title":"Pickle 序列化对象","anchor":"pickling-objects","children":[]},{"title":"其他模型实例方法","anchor":"other-model-instance-methods","children":[{"title":"__str__()","anchor":"str","children":[]},{"title":"__eq__()","anchor":"eq","children":[]},{"title":"__hash__()","anchor":"hash","children":[]},{"title":"get_absolute_url()","anchor":"get-absolute-url","children":[]}]},{"title":"额外的实例方法","anchor":"extra-instance-methods","children":[]},{"title":"其他属性","anchor":"other-attributes","children":[{"title":"_state","anchor":"state","children":[]}]}],"breadcrumbs":[{"docname":"ref/index","title":"API 参考","url":"/zh-hans/4.1/ref/"},{"docname":"ref/models/index","title":"模型","url":"/zh-hans/4.1/ref/models/"}],"prev":{"docname":"ref/models/options","title":"模型 Meta 选项","url":"/zh-hans/4.1/ref/models/options/"},"next":{"docname":"ref/models/querysets","title":"QuerySet API 参考","url":"/zh-hans/4.1/ref/models/querysets/"},"formats":{"html":"/zh-hans/4.1/ref/models/instances/","markdown":"/zh-hans/4.1/ref/models/instances.md","json":"/zh-hans/4.1/ref/models/instances.json"},"source":"https://github.com/django/django/blob/stable/4.1.x/docs/ref/models/instances.txt","official":"https://docs.djangoproject.com/zh-hans/4.1/ref/models/instances/","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","it","pt-br","ko","es","el","pl"]}