{"title":"条件表达式","version":"3.1","locale":"zh-hans","docname":"ref/models/conditional-expressions","url":"/zh-hans/3.1/ref/models/conditional-expressions/","canonical":"https://djangodocs.dev/zh-hans/3.1/ref/models/conditional-expressions/","summary":"条件表达式让你可以在过滤器、注解、聚合和更新中使用 if... elif... else 逻辑。条件表达式对表的每条记录执行一系列条件，并返回匹配的结果表达式。","html":"<h1>条件表达式<a class=\"heading-anchor\" href=\"#conditional-expressions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>条件表达式让你可以在过滤器、注解、聚合和更新中使用 <a class=\"reference external\" href=\"https://docs.python.org/3/reference/compound_stmts.html#if\" title=\"(in Python v3.14)\"><code class=\"xref std std-keyword docutils literal notranslate\">if</code></a> ... <a class=\"reference external\" href=\"https://docs.python.org/3/reference/compound_stmts.html#elif\" title=\"(in Python v3.14)\"><code class=\"xref std std-keyword docutils literal notranslate\">elif</code></a> ... <a class=\"reference external\" href=\"https://docs.python.org/3/reference/compound_stmts.html#else\" title=\"(in Python v3.14)\"><code class=\"xref std std-keyword docutils literal notranslate\">else</code></a> 逻辑。条件表达式对表的每条记录执行一系列条件，并返回匹配的结果表达式。条件表达式也可以像其他 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/expressions/\"><span class=\"doc\">表达式</span></a> 一样进行组合和嵌套。</p>\n<section id=\"the-conditional-expression-classes\">\n<h2>条件表达式类<a class=\"heading-anchor\" href=\"#the-conditional-expression-classes\"><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=\"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\">Client</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    REGULAR <span class=\"o\">=</span> <span class=\"s1\">&#39;R&#39;</span>\n    GOLD <span class=\"o\">=</span> <span class=\"s1\">&#39;G&#39;</span>\n    PLATINUM <span class=\"o\">=</span> <span class=\"s1\">&#39;P&#39;</span>\n    ACCOUNT_TYPE_CHOICES <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span>REGULAR<span class=\"p\">,</span> <span class=\"s1\">&#39;Regular&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span>GOLD<span class=\"p\">,</span> <span class=\"s1\">&#39;Gold&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span>PLATINUM<span class=\"p\">,</span> <span class=\"s1\">&#39;Platinum&#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\">50</span><span class=\"p\">)</span>\n    registered_on <span class=\"o\">=</span> models<span class=\"o\">.</span>DateField<span class=\"p\">()</span>\n    account_type <span class=\"o\">=</span> models<span class=\"o\">.</span>CharField<span class=\"p\">(</span>\n        max_length<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">,</span>\n        choices<span class=\"o\">=</span>ACCOUNT_TYPE_CHOICES<span class=\"p\">,</span>\n        default<span class=\"o\">=</span>REGULAR<span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<section id=\"when\">\n<h3><code class=\"docutils literal notranslate\">When</code><a class=\"heading-anchor\" href=\"#when\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.When\">\n<em class=\"property\"><span class=\"k\">class</span> </em><span class=\"sig-name descname\">When</span><span class=\"sig-paren\">(</span><em class=\"sig-param\">condition<span class=\"o\">=</span><span class=\"default_value\">None</span></em>, <em class=\"sig-param\">then<span class=\"o\">=</span><span class=\"default_value\">None</span></em>, <em class=\"sig-param\"><span class=\"o\">**</span>lookups</em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.When\"><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\">When()</code> 对象用于封装一个条件及其结果，以便在条件表达式中使用。使用 <code class=\"docutils literal notranslate\">When()</code> 对象类似于使用 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/querysets/#django.db.models.query.QuerySet.filter\" title=\"django.db.models.query.QuerySet.filter\"><code class=\"xref py py-meth docutils literal notranslate\">filter()</code></a> 方法。可以使用 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/querysets/#field-lookups\"><span class=\"std std-ref\">字段查找</span></a>、 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/querysets/#django.db.models.Q\" title=\"django.db.models.Q\"><code class=\"xref py py-class docutils literal notranslate\">Q</code></a> 对象或 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/expressions/#django.db.models.Expression\" title=\"django.db.models.Expression\"><code class=\"xref py py-class docutils literal notranslate\">Expression</code></a> 对象来指定条件，这些对象的 output_field 是 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/fields/#django.db.models.BooleanField\" title=\"django.db.models.BooleanField\"><code class=\"xref py py-class docutils literal notranslate\">BooleanField</code></a>。结果是用 <code class=\"docutils literal notranslate\">then</code> 关键字提供的。</p>\n<aside class=\"version-note version-changed\" data-version=\"3.0\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 3.0</p><p>增加了对布尔 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/expressions/#django.db.models.Expression\" title=\"django.db.models.Expression\"><code class=\"xref py py-class docutils literal notranslate\">Expression</code></a> 的支持。</p>\n</aside>\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><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> F<span class=\"p\">,</span> Q<span class=\"p\">,</span> When\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># String arguments refer to fields; the following two examples are equivalent:</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>When<span class=\"p\">(</span>account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>GOLD<span class=\"p\">,</span> then<span class=\"o\">=</span><span class=\"s1\">&#39;name&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>When<span class=\"p\">(</span>account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>GOLD<span class=\"p\">,</span> then<span class=\"o\">=</span>F<span class=\"p\">(</span><span class=\"s1\">&#39;name&#39;</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># You can use field lookups in the condition</span>\n<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>When<span class=\"p\">(</span>registered_on__gt<span class=\"o\">=</span>date<span class=\"p\">(</span><span class=\"mi\">2014</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>     registered_on__lt<span class=\"o\">=</span>date<span class=\"p\">(</span><span class=\"mi\">2015</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"mi\">1</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>     then<span class=\"o\">=</span><span class=\"s1\">&#39;account_type&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># Complex conditions can be created using Q objects</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>When<span class=\"p\">(</span>Q<span class=\"p\">(</span>name__startswith<span class=\"o\">=</span><span class=\"s2\">&quot;John&quot;</span><span class=\"p\">)</span> <span class=\"o\">|</span> Q<span class=\"p\">(</span>name__startswith<span class=\"o\">=</span><span class=\"s2\">&quot;Paul&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>     then<span class=\"o\">=</span><span class=\"s1\">&#39;name&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># Condition can be created using boolean expressions.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Exists<span class=\"p\">,</span> OuterRef\n<span class=\"gp\">&gt;&gt;&gt; </span>non_unique_account_type <span class=\"o\">=</span> Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    account_type<span class=\"o\">=</span>OuterRef<span class=\"p\">(</span><span class=\"s1\">&#39;account_type&#39;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span><span class=\"o\">.</span>exclude<span class=\"p\">(</span>pk<span class=\"o\">=</span>OuterRef<span class=\"p\">(</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">))</span><span class=\"o\">.</span>values<span class=\"p\">(</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>When<span class=\"p\">(</span>Exists<span class=\"p\">(</span>non_unique_account_type<span class=\"p\">),</span> then<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s1\">&#39;non unique&#39;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>请记住，每个值都可以是一个表达式。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>由于 <code class=\"docutils literal notranslate\">then</code> 关键字参数是为 <code class=\"docutils literal notranslate\">When()</code> 的结果保留的，所以如果一个 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/instances/#django.db.models.Model\" title=\"django.db.models.Model\"><code class=\"xref py py-class docutils literal notranslate\">Model</code></a> 有一个名为 <code class=\"docutils literal notranslate\">then</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>When<span class=\"p\">(</span>then__exact<span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">,</span> then<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>When<span class=\"p\">(</span>Q<span class=\"p\">(</span>then<span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">),</span> then<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n</code></pre></div>\n</aside>\n</section>\n<section id=\"case\">\n<h3><code class=\"docutils literal notranslate\">Case</code><a class=\"heading-anchor\" href=\"#case\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.Case\">\n<em class=\"property\"><span class=\"k\">class</span> </em><span class=\"sig-name descname\">Case</span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\">*</span>cases</em>, <em class=\"sig-param\"><span class=\"o\">**</span>extra</em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.Case\"><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\">Case()</code> 表达式就像 <code class=\"docutils literal notranslate\">Python</code> 中的 <a class=\"reference external\" href=\"https://docs.python.org/3/reference/compound_stmts.html#if\" title=\"(in Python v3.14)\"><code class=\"xref std std-keyword docutils literal notranslate\">if</code></a>... <a class=\"reference external\" href=\"https://docs.python.org/3/reference/compound_stmts.html#elif\" title=\"(in Python v3.14)\"><code class=\"xref std std-keyword docutils literal notranslate\">elif</code></a>... <a class=\"reference external\" href=\"https://docs.python.org/3/reference/compound_stmts.html#else\" title=\"(in Python v3.14)\"><code class=\"xref std std-keyword docutils literal notranslate\">else</code></a> 语句。在提供的 <code class=\"docutils literal notranslate\">When()</code> 对象中的每个 <code class=\"docutils literal notranslate\">condition</code> 按顺序执行，直到执行出一个对的值。从匹配的 <code class=\"docutils literal notranslate\">When()</code> 对象中返回 <code class=\"docutils literal notranslate\">result</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=\"gp\">&gt;&gt;&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">datetime</span> <span class=\"kn\">import</span> date<span class=\"p\">,</span> timedelta\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Case<span class=\"p\">,</span> CharField<span class=\"p\">,</span> Value<span class=\"p\">,</span> When\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    name<span class=\"o\">=</span><span class=\"s1\">&#39;Jane Doe&#39;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>REGULAR<span class=\"p\">,</span>\n<span class=\"gp\">... </span>    registered_on<span class=\"o\">=</span>date<span class=\"o\">.</span>today<span class=\"p\">()</span> <span class=\"o\">-</span> timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">36</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    name<span class=\"o\">=</span><span class=\"s1\">&#39;James Smith&#39;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>GOLD<span class=\"p\">,</span>\n<span class=\"gp\">... </span>    registered_on<span class=\"o\">=</span>date<span class=\"o\">.</span>today<span class=\"p\">()</span> <span class=\"o\">-</span> timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">5</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    name<span class=\"o\">=</span><span class=\"s1\">&#39;Jack Black&#39;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>PLATINUM<span class=\"p\">,</span>\n<span class=\"gp\">... </span>    registered_on<span class=\"o\">=</span>date<span class=\"o\">.</span>today<span class=\"p\">()</span> <span class=\"o\">-</span> timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">10</span> <span class=\"o\">*</span> <span class=\"mi\">365</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># Get the discount for each Client based on the account type</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>annotate<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    discount<span class=\"o\">=</span>Case<span class=\"p\">(</span>\n<span class=\"gp\">... </span>        When<span class=\"p\">(</span>account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>GOLD<span class=\"p\">,</span> then<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s1\">&#39;5%&#39;</span><span class=\"p\">)),</span>\n<span class=\"gp\">... </span>        When<span class=\"p\">(</span>account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>PLATINUM<span class=\"p\">,</span> then<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s1\">&#39;10%&#39;</span><span class=\"p\">)),</span>\n<span class=\"gp\">... </span>        default<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s1\">&#39;0%&#39;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>        output_field<span class=\"o\">=</span>CharField<span class=\"p\">(),</span>\n<span class=\"gp\">... </span>    <span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span><span class=\"o\">.</span>values_list<span class=\"p\">(</span><span class=\"s1\">&#39;name&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;discount&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [(&#39;Jane Doe&#39;, &#39;0%&#39;), (&#39;James Smith&#39;, &#39;5%&#39;), (&#39;Jack Black&#39;, &#39;10%&#39;)]&gt;</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\">Case()</code> 接受任意数量的 <code class=\"docutils literal notranslate\">When()</code> 对象作为单个参数。其他选项是通过关键字参数提供的。如果没有一个条件的值是 <code class=\"docutils literal notranslate\">TRUE</code>，那么将返回用 <code class=\"docutils literal notranslate\">default</code> 关键字参数给出的表达式。如果没有提供 <code class=\"docutils literal notranslate\">default</code> 参数，则使用 <code class=\"docutils literal notranslate\">None</code>。</p>\n<p>如果我们想改变之前的查询，根据 <code class=\"docutils literal notranslate\">Client</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>a_month_ago <span class=\"o\">=</span> date<span class=\"o\">.</span>today<span class=\"p\">()</span> <span class=\"o\">-</span> timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>a_year_ago <span class=\"o\">=</span> date<span class=\"o\">.</span>today<span class=\"p\">()</span> <span class=\"o\">-</span> timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">365</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># Get the discount for each Client based on the registration date</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>annotate<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    discount<span class=\"o\">=</span>Case<span class=\"p\">(</span>\n<span class=\"gp\">... </span>        When<span class=\"p\">(</span>registered_on__lte<span class=\"o\">=</span>a_year_ago<span class=\"p\">,</span> then<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s1\">&#39;10%&#39;</span><span class=\"p\">)),</span>\n<span class=\"gp\">... </span>        When<span class=\"p\">(</span>registered_on__lte<span class=\"o\">=</span>a_month_ago<span class=\"p\">,</span> then<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s1\">&#39;5%&#39;</span><span class=\"p\">)),</span>\n<span class=\"gp\">... </span>        default<span class=\"o\">=</span>Value<span class=\"p\">(</span><span class=\"s1\">&#39;0%&#39;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>        output_field<span class=\"o\">=</span>CharField<span class=\"p\">(),</span>\n<span class=\"gp\">... </span>    <span class=\"p\">)</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span><span class=\"o\">.</span>values_list<span class=\"p\">(</span><span class=\"s1\">&#39;name&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;discount&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [(&#39;Jane Doe&#39;, &#39;5%&#39;), (&#39;James Smith&#39;, &#39;0%&#39;), (&#39;Jack Black&#39;, &#39;10%&#39;)]&gt;</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>请记住，条件是按顺序计算的，所以在上面的例子中，尽管第二个条件同时符合 Jane Doe 和 Jack Black，我们还是得到了正确的结果。这就像在 <code class=\"docutils literal notranslate\">Python</code> 中的 <a class=\"reference external\" href=\"https://docs.python.org/3/reference/compound_stmts.html#if\" title=\"(in Python v3.14)\"><code class=\"xref std std-keyword docutils literal notranslate\">if</code></a>... <a class=\"reference external\" href=\"https://docs.python.org/3/reference/compound_stmts.html#elif\" title=\"(in Python v3.14)\"><code class=\"xref std std-keyword docutils literal notranslate\">elif</code></a>... <a class=\"reference external\" href=\"https://docs.python.org/3/reference/compound_stmts.html#else\" title=\"(in Python v3.14)\"><code class=\"xref std std-keyword docutils literal notranslate\">else</code></a> 语句一样。</p>\n</aside>\n<p><code class=\"docutils literal notranslate\">Case()</code> 也可以在 <code class=\"docutils literal notranslate\">filter()</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>a_month_ago <span class=\"o\">=</span> date<span class=\"o\">.</span>today<span class=\"p\">()</span> <span class=\"o\">-</span> timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>a_year_ago <span class=\"o\">=</span> date<span class=\"o\">.</span>today<span class=\"p\">()</span> <span class=\"o\">-</span> timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">365</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    registered_on__lte<span class=\"o\">=</span>Case<span class=\"p\">(</span>\n<span class=\"gp\">... </span>        When<span class=\"p\">(</span>account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>GOLD<span class=\"p\">,</span> then<span class=\"o\">=</span>a_month_ago<span class=\"p\">),</span>\n<span class=\"gp\">... </span>        When<span class=\"p\">(</span>account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>PLATINUM<span class=\"p\">,</span> then<span class=\"o\">=</span>a_year_ago<span class=\"p\">),</span>\n<span class=\"gp\">... </span>    <span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span><span class=\"o\">.</span>values_list<span class=\"p\">(</span><span class=\"s1\">&#39;name&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;account_type&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [(&#39;Jack Black&#39;, &#39;P&#39;)]&gt;</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"advanced-queries\">\n<h2>高级查询<a class=\"heading-anchor\" href=\"#advanced-queries\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>条件表达式可用于注解、聚合、过滤器、查找和更新中。它们还可以与其他表达式组合和嵌套。这使你可以进行强大的条件查询。</p>\n<section id=\"conditional-update\">\n<h3>条件更新<a class=\"heading-anchor\" href=\"#conditional-update\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>比方说，我们想改变客户的 <code class=\"docutils literal notranslate\">account_type</code> 以匹配他们的注册日期。我们可以使用一个条件表达式和 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/querysets/#django.db.models.query.QuerySet.update\" title=\"django.db.models.query.QuerySet.update\"><code class=\"xref py py-meth docutils literal notranslate\">update()</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>a_month_ago <span class=\"o\">=</span> date<span class=\"o\">.</span>today<span class=\"p\">()</span> <span class=\"o\">-</span> timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">30</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>a_year_ago <span class=\"o\">=</span> date<span class=\"o\">.</span>today<span class=\"p\">()</span> <span class=\"o\">-</span> timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">365</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># Update the account_type for each Client from the registration date</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>update<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    account_type<span class=\"o\">=</span>Case<span class=\"p\">(</span>\n<span class=\"gp\">... </span>        When<span class=\"p\">(</span>registered_on__lte<span class=\"o\">=</span>a_year_ago<span class=\"p\">,</span>\n<span class=\"gp\">... </span>             then<span class=\"o\">=</span>Value<span class=\"p\">(</span>Client<span class=\"o\">.</span>PLATINUM<span class=\"p\">)),</span>\n<span class=\"gp\">... </span>        When<span class=\"p\">(</span>registered_on__lte<span class=\"o\">=</span>a_month_ago<span class=\"p\">,</span>\n<span class=\"gp\">... </span>             then<span class=\"o\">=</span>Value<span class=\"p\">(</span>Client<span class=\"o\">.</span>GOLD<span class=\"p\">)),</span>\n<span class=\"gp\">... </span>        default<span class=\"o\">=</span>Value<span class=\"p\">(</span>Client<span class=\"o\">.</span>REGULAR<span class=\"p\">)</span>\n<span class=\"gp\">... </span>    <span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>values_list<span class=\"p\">(</span><span class=\"s1\">&#39;name&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;account_type&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [(&#39;Jane Doe&#39;, &#39;G&#39;), (&#39;James Smith&#39;, &#39;R&#39;), (&#39;Jack Black&#39;, &#39;P&#39;)]&gt;</span>\n</code></pre></div>\n</section>\n<section id=\"conditional-aggregation\">\n<span id=\"id1\"></span><h3>条件聚合<a class=\"heading-anchor\" href=\"#conditional-aggregation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果我们想知道每个 <code class=\"docutils literal notranslate\">account_type</code> 有多少个客户？我们可以使用 <a class=\"reference internal\" href=\"/zh-hans/3.1/ref/models/querysets/#aggregation-functions\"><span class=\"std std-ref\">聚合函数</span></a> 的 <code class=\"docutils literal notranslate\">filter</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><span class=\"c1\"># Create some more Clients first so we can have something to count</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    name<span class=\"o\">=</span><span class=\"s1\">&#39;Jean Grey&#39;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>REGULAR<span class=\"p\">,</span>\n<span class=\"gp\">... </span>    registered_on<span class=\"o\">=</span>date<span class=\"o\">.</span>today<span class=\"p\">())</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    name<span class=\"o\">=</span><span class=\"s1\">&#39;James Bond&#39;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>PLATINUM<span class=\"p\">,</span>\n<span class=\"gp\">... </span>    registered_on<span class=\"o\">=</span>date<span class=\"o\">.</span>today<span class=\"p\">())</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    name<span class=\"o\">=</span><span class=\"s1\">&#39;Jane Porter&#39;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>PLATINUM<span class=\"p\">,</span>\n<span class=\"gp\">... </span>    registered_on<span class=\"o\">=</span>date<span class=\"o\">.</span>today<span class=\"p\">())</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># Get counts for each value of account_type</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span> <span class=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Count\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>aggregate<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    regular<span class=\"o\">=</span>Count<span class=\"p\">(</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">,</span> <span class=\"nb\">filter</span><span class=\"o\">=</span>Q<span class=\"p\">(</span>account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>REGULAR<span class=\"p\">)),</span>\n<span class=\"gp\">... </span>    gold<span class=\"o\">=</span>Count<span class=\"p\">(</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">,</span> <span class=\"nb\">filter</span><span class=\"o\">=</span>Q<span class=\"p\">(</span>account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>GOLD<span class=\"p\">)),</span>\n<span class=\"gp\">... </span>    platinum<span class=\"o\">=</span>Count<span class=\"p\">(</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">,</span> <span class=\"nb\">filter</span><span class=\"o\">=</span>Q<span class=\"p\">(</span>account_type<span class=\"o\">=</span>Client<span class=\"o\">.</span>PLATINUM<span class=\"p\">)),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n<span class=\"go\">{&#39;regular&#39;: 2, &#39;gold&#39;: 1, &#39;platinum&#39;: 3}</span>\n</code></pre></div>\n<p>在支持 SQL 2003 <code class=\"docutils literal notranslate\">FILTER WHERE</code> 语法的数据库上，这个聚合产生一个查询。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">SELECT</span> <span class=\"k\">count</span><span class=\"p\">(</span><span class=\"s1\">&#39;id&#39;</span><span class=\"p\">)</span> FILTER <span class=\"p\">(</span><span class=\"k\">WHERE</span> account_type<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span> <span class=\"k\">as</span> regular<span class=\"p\">,</span>\n       <span class=\"k\">count</span><span class=\"p\">(</span><span class=\"s1\">&#39;id&#39;</span><span class=\"p\">)</span> FILTER <span class=\"p\">(</span><span class=\"k\">WHERE</span> account_type<span class=\"o\">=</span><span class=\"mi\">2</span><span class=\"p\">)</span> <span class=\"k\">as</span> gold<span class=\"p\">,</span>\n       <span class=\"k\">count</span><span class=\"p\">(</span><span class=\"s1\">&#39;id&#39;</span><span class=\"p\">)</span> FILTER <span class=\"p\">(</span><span class=\"k\">WHERE</span> account_type<span class=\"o\">=</span><span class=\"mi\">3</span><span class=\"p\">)</span> <span class=\"k\">as</span> platinum\n<span class=\"k\">FROM</span> clients<span class=\"p\">;</span>\n</code></pre></div>\n<p>在其他数据库中，这是用 <code class=\"docutils literal notranslate\">CASE</code> 语句模拟的：</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">SELECT</span> <span class=\"k\">count</span><span class=\"p\">(</span><span class=\"k\">CASE</span> <span class=\"k\">WHEN</span> account_type<span class=\"o\">=</span><span class=\"mi\">1</span> <span class=\"k\">THEN</span> id <span class=\"k\">ELSE</span> <span class=\"k\">null</span><span class=\"p\">)</span> <span class=\"k\">as</span> regular<span class=\"p\">,</span>\n       <span class=\"k\">count</span><span class=\"p\">(</span><span class=\"k\">CASE</span> <span class=\"k\">WHEN</span> account_type<span class=\"o\">=</span><span class=\"mi\">2</span> <span class=\"k\">THEN</span> id <span class=\"k\">ELSE</span> <span class=\"k\">null</span><span class=\"p\">)</span> <span class=\"k\">as</span> gold<span class=\"p\">,</span>\n       <span class=\"k\">count</span><span class=\"p\">(</span><span class=\"k\">CASE</span> <span class=\"k\">WHEN</span> account_type<span class=\"o\">=</span><span class=\"mi\">3</span> <span class=\"k\">THEN</span> id <span class=\"k\">ELSE</span> <span class=\"k\">null</span><span class=\"p\">)</span> <span class=\"k\">as</span> platinum\n<span class=\"k\">FROM</span> clients<span class=\"p\">;</span>\n</code></pre></div>\n<p>这两条 SQL 语句在功能上是等同的，但更明确的 <code class=\"docutils literal notranslate\">FILTER</code> 可能表现得更好。</p>\n</section>\n<section id=\"conditional-filter\">\n<h3>条件过滤<a class=\"heading-anchor\" href=\"#conditional-filter\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<aside class=\"version-note version-added\" data-version=\"3.0\" role=\"note\">\n<p class=\"version-note-title\">New in Django 3.0</p></aside>\n<p>当条件表达式返回一个布尔值时，可以直接在过滤器中使用它。这意味着它不会被添加到 <code class=\"docutils literal notranslate\">SELECT</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>non_unique_account_type <span class=\"o\">=</span> Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>\n<span class=\"gp\">... </span>    account_type<span class=\"o\">=</span>OuterRef<span class=\"p\">(</span><span class=\"s1\">&#39;account_type&#39;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span><span class=\"o\">.</span>exclude<span class=\"p\">(</span>pk<span class=\"o\">=</span>OuterRef<span class=\"p\">(</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">))</span><span class=\"o\">.</span>values<span class=\"p\">(</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>Client<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span><span class=\"o\">~</span>Exists<span class=\"p\">(</span>non_unique_account_type<span class=\"p\">))</span>\n</code></pre></div>\n<p>用 SQL 术语来说，它的值是：</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</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=\"SQL code\"><code><span class=\"k\">SELECT</span> <span class=\"p\">...</span>\n<span class=\"k\">FROM</span> client c0\n<span class=\"k\">WHERE</span> <span class=\"k\">NOT</span> <span class=\"k\">EXISTS</span> <span class=\"p\">(</span>\n  <span class=\"k\">SELECT</span> c1<span class=\"p\">.</span>id\n  <span class=\"k\">FROM</span> client c1\n  <span class=\"k\">WHERE</span> c1<span class=\"p\">.</span>account_type <span class=\"o\">=</span> c0<span class=\"p\">.</span>account_type <span class=\"k\">AND</span> <span class=\"k\">NOT</span> c1<span class=\"p\">.</span>id <span class=\"o\">=</span> c0<span class=\"p\">.</span>id\n<span class=\"p\">)</span>\n</code></pre></div>\n</section>\n</section>","rootId":"conditional-expressions","toc":[{"title":"条件表达式类","anchor":"the-conditional-expression-classes","children":[{"title":"When","anchor":"when","children":[]},{"title":"Case","anchor":"case","children":[]}]},{"title":"高级查询","anchor":"advanced-queries","children":[{"title":"条件更新","anchor":"conditional-update","children":[]},{"title":"条件聚合","anchor":"conditional-aggregation","children":[]},{"title":"条件过滤","anchor":"conditional-filter","children":[]}]}],"breadcrumbs":[{"docname":"ref/index","title":"API 参考","url":"/zh-hans/3.1/ref/"},{"docname":"ref/models/index","title":"模型","url":"/zh-hans/3.1/ref/models/"}],"prev":{"docname":"ref/models/expressions","title":"查询表达式","url":"/zh-hans/3.1/ref/models/expressions/"},"next":{"docname":"ref/models/database-functions","title":"数据库函数","url":"/zh-hans/3.1/ref/models/database-functions/"},"formats":{"html":"/zh-hans/3.1/ref/models/conditional-expressions/","markdown":"/zh-hans/3.1/ref/models/conditional-expressions.md","json":"/zh-hans/3.1/ref/models/conditional-expressions.json"},"source":"https://github.com/django/django/blob/stable/3.1.x/docs/ref/models/conditional-expressions.txt","official":"https://docs.djangoproject.com/zh-hans/3.1/ref/models/conditional-expressions/","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"]}