{"title":"多对一关联","version":"3.0","locale":"zh-hans","docname":"topics/db/examples/many_to_one","url":"/zh-hans/3.0/topics/db/examples/many_to_one/","canonical":"https://djangodocs.dev/zh-hans/3.0/topics/db/examples/many_to_one/","summary":"要定义一个多对一关联，使用 ForeignKey. 下面是可以使用PythonAPI工具执行的操作示例。","html":"<h1>多对一关联<a class=\"heading-anchor\" href=\"#many-to-one-relationships\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>要定义一个多对一关联，使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\">ForeignKey</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.db</span> <span class=\"kn\">import</span> models\n\n<span class=\"k\">class</span> <span class=\"nc\">Reporter</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\">30</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\">30</span><span class=\"p\">)</span>\n    email <span class=\"o\">=</span> models<span class=\"o\">.</span>EmailField<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=\"s2\">&quot;</span><span class=\"si\">%s</span><span class=\"s2\"> </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</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\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    headline <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    pub_date <span class=\"o\">=</span> models<span class=\"o\">.</span>DateField<span class=\"p\">()</span>\n    reporter <span class=\"o\">=</span> models<span class=\"o\">.</span>ForeignKey<span class=\"p\">(</span>Reporter<span class=\"p\">,</span> on_delete<span class=\"o\">=</span>models<span class=\"o\">.</span>CASCADE<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=\"bp\">self</span><span class=\"o\">.</span>headline\n\n    <span class=\"k\">class</span> <span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        ordering <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;headline&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>下面是可以使用PythonAPI工具执行的操作示例。</p>\n<p>创建一些 Reporters：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>r <span class=\"o\">=</span> Reporter<span class=\"p\">(</span>first_name<span class=\"o\">=</span><span class=\"s1\">&#39;John&#39;</span><span class=\"p\">,</span> last_name<span class=\"o\">=</span><span class=\"s1\">&#39;Smith&#39;</span><span class=\"p\">,</span> email<span class=\"o\">=</span><span class=\"s1\">&#39;john@example.com&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>r<span class=\"o\">.</span>save<span class=\"p\">()</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>r2 <span class=\"o\">=</span> Reporter<span class=\"p\">(</span>first_name<span class=\"o\">=</span><span class=\"s1\">&#39;Paul&#39;</span><span class=\"p\">,</span> last_name<span class=\"o\">=</span><span class=\"s1\">&#39;Jones&#39;</span><span class=\"p\">,</span> email<span class=\"o\">=</span><span class=\"s1\">&#39;paul@example.com&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>r2<span class=\"o\">.</span>save<span class=\"p\">()</span>\n</code></pre></div>\n<p>创建一个 Article：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">datetime</span> <span class=\"kn\">import</span> date\n<span class=\"gp\">&gt;&gt;&gt; </span>a <span class=\"o\">=</span> Article<span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> headline<span class=\"o\">=</span><span class=\"s2\">&quot;This is a test&quot;</span><span class=\"p\">,</span> pub_date<span class=\"o\">=</span>date<span class=\"p\">(</span><span class=\"mi\">2005</span><span class=\"p\">,</span> <span class=\"mi\">7</span><span class=\"p\">,</span> <span class=\"mi\">27</span><span class=\"p\">),</span> reporter<span class=\"o\">=</span>r<span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>a<span class=\"o\">.</span>save<span class=\"p\">()</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>a<span class=\"o\">.</span>reporter<span class=\"o\">.</span>id\n<span class=\"go\">1</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>a<span class=\"o\">.</span>reporter\n<span class=\"go\">&lt;Reporter: John Smith&gt;</span>\n</code></pre></div>\n<p>注意你必须先保存对象，然后再给它指定外键关系。比如，使用未保存的 <code class=\"docutils literal notranslate\">Reporter</code> 创建 <code class=\"docutils literal notranslate\">Article</code> ，会引发 <code class=\"docutils literal notranslate\">ValueError</code>：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>r3 <span class=\"o\">=</span> Reporter<span class=\"p\">(</span>first_name<span class=\"o\">=</span><span class=\"s1\">&#39;John&#39;</span><span class=\"p\">,</span> last_name<span class=\"o\">=</span><span class=\"s1\">&#39;Smith&#39;</span><span class=\"p\">,</span> email<span class=\"o\">=</span><span class=\"s1\">&#39;john@example.com&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>headline<span class=\"o\">=</span><span class=\"s2\">&quot;This is a test&quot;</span><span class=\"p\">,</span> pub_date<span class=\"o\">=</span>date<span class=\"p\">(</span><span class=\"mi\">2005</span><span class=\"p\">,</span> <span class=\"mi\">7</span><span class=\"p\">,</span> <span class=\"mi\">27</span><span class=\"p\">),</span> reporter<span class=\"o\">=</span>r3<span class=\"p\">)</span>\n<span class=\"gt\">Traceback (most recent call last):</span>\n<span class=\"c\">...</span>\n<span class=\"gr\">ValueError</span>: save() prohibited to prevent data loss due to unsaved related object &#39;reporter&#39;.\n</code></pre></div>\n<p>Article 对象可以访问与它们相关联的 Reporter 对象：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>r <span class=\"o\">=</span> a<span class=\"o\">.</span>reporter\n</code></pre></div>\n<p>通过 Reporter 对象来创建一个 Article</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>new_article <span class=\"o\">=</span> r<span class=\"o\">.</span>article_set<span class=\"o\">.</span>create<span class=\"p\">(</span>headline<span class=\"o\">=</span><span class=\"s2\">&quot;John&#39;s second story&quot;</span><span class=\"p\">,</span> pub_date<span class=\"o\">=</span>date<span class=\"p\">(</span><span class=\"mi\">2005</span><span class=\"p\">,</span> <span class=\"mi\">7</span><span class=\"p\">,</span> <span class=\"mi\">29</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_article\n<span class=\"go\">&lt;Article: John&#39;s second story&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_article<span class=\"o\">.</span>reporter\n<span class=\"go\">&lt;Reporter: John Smith&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_article<span class=\"o\">.</span>reporter<span class=\"o\">.</span>id\n<span class=\"go\">1</span>\n</code></pre></div>\n<p>创建一个新的article：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>new_article2 <span class=\"o\">=</span> Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>headline<span class=\"o\">=</span><span class=\"s2\">&quot;Paul&#39;s story&quot;</span><span class=\"p\">,</span> pub_date<span class=\"o\">=</span>date<span class=\"p\">(</span><span class=\"mi\">2006</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">17</span><span class=\"p\">),</span> reporter<span class=\"o\">=</span>r<span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_article2<span class=\"o\">.</span>reporter\n<span class=\"go\">&lt;Reporter: John Smith&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_article2<span class=\"o\">.</span>reporter<span class=\"o\">.</span>id\n<span class=\"go\">1</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>r<span class=\"o\">.</span>article_set<span class=\"o\">.</span>all<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: Paul&#39;s story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n</code></pre></div>\n<p>添加相同的article到一个不同的article集合，请观察它怎么移动：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>r2<span class=\"o\">.</span>article_set<span class=\"o\">.</span>add<span class=\"p\">(</span>new_article2<span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_article2<span class=\"o\">.</span>reporter<span class=\"o\">.</span>id\n<span class=\"go\">2</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>new_article2<span class=\"o\">.</span>reporter\n<span class=\"go\">&lt;Reporter: Paul Jones&gt;</span>\n</code></pre></div>\n<p>添加错误类型的对象，会引发TypeError：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>r<span class=\"o\">.</span>article_set<span class=\"o\">.</span>add<span class=\"p\">(</span>r2<span class=\"p\">)</span>\n<span class=\"gt\">Traceback (most recent call last):</span>\n<span class=\"c\">...</span>\n<span class=\"gr\">TypeError</span>: &#39;Article&#39; instance expected, got &lt;Reporter: Paul Jones&gt;\n\n<span class=\"gp\">&gt;&gt;&gt; </span>r<span class=\"o\">.</span>article_set<span class=\"o\">.</span>all<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>r2<span class=\"o\">.</span>article_set<span class=\"o\">.</span>all<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: Paul&#39;s story&gt;]&gt;</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>r<span class=\"o\">.</span>article_set<span class=\"o\">.</span>count<span class=\"p\">()</span>\n<span class=\"go\">2</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>r2<span class=\"o\">.</span>article_set<span class=\"o\">.</span>count<span class=\"p\">()</span>\n<span class=\"go\">1</span>\n</code></pre></div>\n<p>注意在最后的例子里，那篇 article 的 reporter 已经从 John 变为 Paul。</p>\n<p>相关管理器也提供字段查询。只要你需要，API会自动跟踪关系，使用双下划线来分隔，你可以根据需要获取深层关系。这没有限制。比如：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>r<span class=\"o\">.</span>article_set<span class=\"o\">.</span>filter<span class=\"p\">(</span>headline__startswith<span class=\"o\">=</span><span class=\"s1\">&#39;This&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: This is a test&gt;]&gt;</span>\n\n<span class=\"go\"># Find all Articles for any Reporter whose first name is &quot;John&quot;.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>reporter__first_name<span class=\"o\">=</span><span class=\"s1\">&#39;John&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n</code></pre></div>\n<p>这里的查询是完全匹配：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>reporter__first_name<span class=\"o\">=</span><span class=\"s1\">&#39;John&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n</code></pre></div>\n<p>在相关字段上查询两次。这里转化成WHERE从句里的AND条件。</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>reporter__first_name<span class=\"o\">=</span><span class=\"s1\">&#39;John&#39;</span><span class=\"p\">,</span> reporter__last_name<span class=\"o\">=</span><span class=\"s1\">&#39;Smith&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n</code></pre></div>\n<p>对于相关查询，你可以提供主键值或显式传递相关对象：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>reporter__pk<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>reporter<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>reporter<span class=\"o\">=</span>r<span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>reporter__in<span class=\"o\">=</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">,</span><span class=\"mi\">2</span><span class=\"p\">])</span><span class=\"o\">.</span>distinct<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: Paul&#39;s story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>reporter__in<span class=\"o\">=</span><span class=\"p\">[</span>r<span class=\"p\">,</span>r2<span class=\"p\">])</span><span class=\"o\">.</span>distinct<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: Paul&#39;s story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n</code></pre></div>\n<p>你也可以使用查询集而不是实例的文字列表：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>reporter__in<span class=\"o\">=</span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>first_name<span class=\"o\">=</span><span class=\"s1\">&#39;John&#39;</span><span class=\"p\">))</span><span class=\"o\">.</span>distinct<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n</code></pre></div>\n<p>反向查询：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article__pk<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article<span class=\"o\">=</span>a<span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;]&gt;</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article__headline__startswith<span class=\"o\">=</span><span class=\"s1\">&#39;This&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;, &lt;Reporter: John Smith&gt;, &lt;Reporter: John Smith&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article__headline__startswith<span class=\"o\">=</span><span class=\"s1\">&#39;This&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span>distinct<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;]&gt;</span>\n</code></pre></div>\n<p>反向查询的计数与 distinct() ：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article__headline__startswith<span class=\"o\">=</span><span class=\"s1\">&#39;This&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span>count<span class=\"p\">()</span>\n<span class=\"go\">3</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article__headline__startswith<span class=\"o\">=</span><span class=\"s1\">&#39;This&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span>distinct<span class=\"p\">()</span><span class=\"o\">.</span>count<span class=\"p\">()</span>\n<span class=\"go\">1</span>\n</code></pre></div>\n<p>可以循环查询：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article__reporter__first_name__startswith<span class=\"o\">=</span><span class=\"s1\">&#39;John&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;, &lt;Reporter: John Smith&gt;, &lt;Reporter: John Smith&gt;, &lt;Reporter: John Smith&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article__reporter__first_name__startswith<span class=\"o\">=</span><span class=\"s1\">&#39;John&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span>distinct<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article__reporter<span class=\"o\">=</span>r<span class=\"p\">)</span><span class=\"o\">.</span>distinct<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;]&gt;</span>\n</code></pre></div>\n<p>如果删除了一个reporter，他的articles将被删除（假设使用设置了 <code class=\"docutils literal notranslate\">CASCADE</code> 的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/models/fields/#django.db.models.ForeignKey.on_delete\" title=\"django.db.models.ForeignKey.on_delete\"><code class=\"xref py py-attr docutils literal notranslate\">django.db.models.ForeignKey.on_delete</code></a> 来定义主键，这是默认设置）：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>all<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: Paul&#39;s story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>order_by<span class=\"p\">(</span><span class=\"s1\">&#39;first_name&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;, &lt;Reporter: Paul Jones&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>r2<span class=\"o\">.</span>delete<span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>all<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Article: John&#39;s second story&gt;, &lt;Article: This is a test&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>order_by<span class=\"p\">(</span><span class=\"s1\">&#39;first_name&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Reporter: John Smith&gt;]&gt;</span>\n</code></pre></div>\n<p>可以在查询中使用JOIN进行删除：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>article__headline__startswith<span class=\"o\">=</span><span class=\"s1\">&#39;This&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span>delete<span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Reporter<span class=\"o\">.</span>objects<span class=\"o\">.</span>all<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet []&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Article<span class=\"o\">.</span>objects<span class=\"o\">.</span>all<span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet []&gt;</span>\n</code></pre></div>","rootId":"many-to-one-relationships","toc":[],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/3.0/topics/"},{"docname":"topics/db/index","title":"模型和数据库","url":"/zh-hans/3.0/topics/db/"},{"docname":"topics/db/examples/index","title":"模型关联 API 用法示例","url":"/zh-hans/3.0/topics/db/examples/"}],"prev":{"docname":"topics/db/examples/many_to_many","title":"多对多关联","url":"/zh-hans/3.0/topics/db/examples/many_to_many/"},"next":{"docname":"topics/db/examples/one_to_one","title":"一对一关联","url":"/zh-hans/3.0/topics/db/examples/one_to_one/"},"formats":{"html":"/zh-hans/3.0/topics/db/examples/many_to_one/","markdown":"/zh-hans/3.0/topics/db/examples/many_to_one.md","json":"/zh-hans/3.0/topics/db/examples/many_to_one.json"},"source":"https://github.com/django/django/blob/stable/3.0.x/docs/topics/db/examples/many_to_one.txt","official":"https://docs.djangoproject.com/zh-hans/3.0/topics/db/examples/many_to_one/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}