{"title":"查询表达式","version":"5.1","locale":"zh-hans","docname":"ref/models/expressions","url":"/zh-hans/5.1/ref/models/expressions/","canonical":"https://djangodocs.dev/zh-hans/5.1/ref/models/expressions/","summary":"查询表达式描述了一个值或一个计算，它可以作为更新、创建、过滤、排序、注解或聚合的一部分。当一个表达式输出一个布尔值时，它可以直接用于过滤器中。有许多内置的表达式（在下面的文档中）可以用来帮助你编写查询。表达式可以组合，或者在某些情况下嵌套，以形成更复杂的计算。 支持的算术 Link to this heading #…","html":"<h1>查询表达式<a class=\"heading-anchor\" href=\"#query-expressions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>查询表达式描述了一个值或一个计算，它可以作为更新、创建、过滤、排序、注解或聚合的一部分。当一个表达式输出一个布尔值时，它可以直接用于过滤器中。有许多内置的表达式（在下面的文档中）可以用来帮助你编写查询。表达式可以组合，或者在某些情况下嵌套，以形成更复杂的计算。</p>\n<section id=\"supported-arithmetic\">\n<h2>支持的算术<a class=\"heading-anchor\" href=\"#supported-arithmetic\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django 支持负、加、减、乘、除、模数运算，以及对查询表达式的幂运算符，使用 Python 常量、变量，甚至其他表达式。</p>\n</section>\n<section id=\"output-field\">\n<span id=\"id1\"></span><h2>输出字段<a class=\"heading-anchor\" href=\"#output-field\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>这一部分文档中许多表达式都支持一个可选的 <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></code> 参数。如果提供，Django 将在从数据库中检索该值后将其加载到该字段中。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></code> 接受一个模型字段实例，例如 <code class=\"docutils literal notranslate\"><span class=\"pre\">IntegerField()</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">BooleanField()</span></code>。通常，该字段不需要任何参数，如 <code class=\"docutils literal notranslate\"><span class=\"pre\">max_length</span></code>，因为字段参数与数据验证相关，不会在表达式的输出值上执行。</p>\n<p>只有在 Django 无法自动确定结果的字段类型时，才需要使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></code>，例如混合字段类型的复杂表达式。例如，添加一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">DecimalField()</span></code> 和一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">FloatField()</span></code> 需要一个输出字段，如 <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field=FloatField()</span></code>。</p>\n</section>\n<section id=\"some-examples\">\n<h2>一些例子<a class=\"heading-anchor\" href=\"#some-examples\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\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=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Count</span><span class=\"p\">,</span> <span class=\"n\">F</span><span class=\"p\">,</span> <span class=\"n\">Value</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models.functions</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Length</span><span class=\"p\">,</span> <span class=\"n\">Upper</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models.lookups</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">GreaterThan</span>\n\n<span class=\"go\"># Find companies that have more employees than chairs.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">num_employees__gt</span><span class=\"o\">=</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_chairs&quot;</span><span class=\"p\">))</span>\n\n<span class=\"go\"># Find companies that have at least twice as many employees</span>\n<span class=\"go\"># as chairs. Both the querysets below are equivalent.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">num_employees__gt</span><span class=\"o\">=</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_chairs&quot;</span><span class=\"p\">)</span> <span class=\"o\">*</span> <span class=\"mi\">2</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">num_employees__gt</span><span class=\"o\">=</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_chairs&quot;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_chairs&quot;</span><span class=\"p\">))</span>\n\n<span class=\"go\"># How many chairs are needed for each company to seat all employees?</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">company</span> <span class=\"o\">=</span> <span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">num_employees__gt</span><span class=\"o\">=</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_chairs&quot;</span><span class=\"p\">))</span>\n<span class=\"gp\">... </span>    <span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">chairs_needed</span><span class=\"o\">=</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_employees&quot;</span><span class=\"p\">)</span> <span class=\"o\">-</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_chairs&quot;</span><span class=\"p\">))</span>\n<span class=\"gp\">... </span>    <span class=\"o\">.</span><span class=\"n\">first</span><span class=\"p\">()</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">company</span><span class=\"o\">.</span><span class=\"n\">num_employees</span>\n<span class=\"go\">120</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">company</span><span class=\"o\">.</span><span class=\"n\">num_chairs</span>\n<span class=\"go\">50</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">company</span><span class=\"o\">.</span><span class=\"n\">chairs_needed</span>\n<span class=\"go\">70</span>\n\n<span class=\"go\"># Create a new company using expressions.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">company</span> <span class=\"o\">=</span> <span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;Google&quot;</span><span class=\"p\">,</span> <span class=\"n\">ticker</span><span class=\"o\">=</span><span class=\"n\">Upper</span><span class=\"p\">(</span><span class=\"n\">Value</span><span class=\"p\">(</span><span class=\"s2\">&quot;goog&quot;</span><span class=\"p\">)))</span>\n<span class=\"go\"># Be sure to refresh it if you need to access the field.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">company</span><span class=\"o\">.</span><span class=\"n\">refresh_from_db</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">company</span><span class=\"o\">.</span><span class=\"n\">ticker</span>\n<span class=\"go\">&#39;GOOG&#39;</span>\n\n<span class=\"go\"># Annotate models with an aggregated value. Both forms</span>\n<span class=\"go\"># below are equivalent.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">num_products</span><span class=\"o\">=</span><span class=\"n\">Count</span><span class=\"p\">(</span><span class=\"s2\">&quot;products&quot;</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">num_products</span><span class=\"o\">=</span><span class=\"n\">Count</span><span class=\"p\">(</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;products&quot;</span><span class=\"p\">)))</span>\n\n<span class=\"go\"># Aggregates can contain complex computations also</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">num_offerings</span><span class=\"o\">=</span><span class=\"n\">Count</span><span class=\"p\">(</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;products&quot;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;services&quot;</span><span class=\"p\">)))</span>\n\n<span class=\"go\"># Expressions can also be used in order_by(), either directly</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"n\">Length</span><span class=\"p\">(</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">asc</span><span class=\"p\">())</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"n\">Length</span><span class=\"p\">(</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">desc</span><span class=\"p\">())</span>\n<span class=\"go\"># or using the double underscore lookup syntax.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">CharField</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models.functions</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Length</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">CharField</span><span class=\"o\">.</span><span class=\"n\">register_lookup</span><span class=\"p\">(</span><span class=\"n\">Length</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s2\">&quot;name__length&quot;</span><span class=\"p\">)</span>\n\n<span class=\"go\"># Boolean expression can be used directly in filters.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Exists</span><span class=\"p\">,</span> <span class=\"n\">OuterRef</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">Exists</span><span class=\"p\">(</span><span class=\"n\">Employee</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">company</span><span class=\"o\">=</span><span class=\"n\">OuterRef</span><span class=\"p\">(</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">),</span> <span class=\"n\">salary__gt</span><span class=\"o\">=</span><span class=\"mi\">10</span><span class=\"p\">))</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n\n<span class=\"go\"># Lookup expressions can also be used directly in filters</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">GreaterThan</span><span class=\"p\">(</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_employees&quot;</span><span class=\"p\">),</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_chairs&quot;</span><span class=\"p\">)))</span>\n<span class=\"go\"># or annotations.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">need_chairs</span><span class=\"o\">=</span><span class=\"n\">GreaterThan</span><span class=\"p\">(</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_employees&quot;</span><span class=\"p\">),</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_chairs&quot;</span><span class=\"p\">)),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"built-in-expressions\">\n<h2>内置表达式<a class=\"heading-anchor\" href=\"#built-in-expressions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>这些表达式在 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.models.expressions</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.models.aggregates</span></code> 中定义，但为了方便起见，通常从 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/db/models/#module-django.db.models\" title=\"django.db.models\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.db.models</span></code></a> 中导入使用。</p>\n</aside>\n<section id=\"f-expressions\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 表达式<a class=\"heading-anchor\" href=\"#f-expressions\"><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.F\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">F</span></span><a class=\"heading-anchor\" href=\"#django.db.models.F\"><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\"><span class=\"pre\">F()</span></code> 对象表示模型字段的值、模型字段的转换值或注释列的值。它使得可以引用模型字段的值并对其执行数据库操作，而无需实际将它们从数据库提取到 Python 内存中。</p>\n<p>取而代之的是，Django 使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 对象来生成一个 SQL 表达式，在数据库层面描述所需的操作。</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=\"c1\"># Tintin filed a news story!</span>\n<span class=\"n\">reporter</span> <span class=\"o\">=</span> <span class=\"n\">Reporters</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;Tintin&quot;</span><span class=\"p\">)</span>\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">stories_filed</span> <span class=\"o\">+=</span> <span class=\"mi\">1</span>\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>这里，我们从数据库中提取了 <code class=\"docutils literal notranslate\"><span class=\"pre\">reporter.stories_filed</span></code> 的值到内存中，并使用熟悉的 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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">F</span>\n\n<span class=\"n\">reporter</span> <span class=\"o\">=</span> <span class=\"n\">Reporters</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;Tintin&quot;</span><span class=\"p\">)</span>\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">stories_filed</span> <span class=\"o\">=</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;stories_filed&quot;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"mi\">1</span>\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>虽然 <code class=\"docutils literal notranslate\"><span class=\"pre\">reporter.stories_filed</span> <span class=\"pre\">=</span> <span class=\"pre\">F('stories_filed')</span> <span class=\"pre\">+</span> <span class=\"pre\">1</span></code> 看起来像一个普通的 Python 赋值给一个实例属性，但实际上它是一个描述数据库操作的 SQL 结构。</p>\n<p>当 Django 遇到 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 的实例时，它会覆盖标准的 Python 运算符来创建一个封装的 SQL 表达式；在本例中，它指示数据库递增由 <code class=\"docutils literal notranslate\"><span class=\"pre\">reporter.stories_filed</span></code> 表示的数据库字段。</p>\n<p>无论 <code class=\"docutils literal notranslate\"><span class=\"pre\">reporter.stories_filed</span></code> 上的值是多少，Python 永远不会知道它——它完全由数据库处理。通过 Django 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 类，Python 所做的就是创建 SQL 语法来引用这个字段并描述操作。</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=\"n\">reporter</span> <span class=\"o\">=</span> <span class=\"n\">Reporters</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">pk</span><span class=\"p\">)</span>\n<span class=\"c1\"># Or, more succinctly:</span>\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">refresh_from_db</span><span class=\"p\">()</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 除了用于上述对单个实例的操作外，<code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 还可以与 <code class=\"docutils literal notranslate\"><span class=\"pre\">update()</span></code> 一起用于对象实例的 <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySets</span></code>。这就把我们上面使用的两个查询——<code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> 和 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/instances/#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">save()</span></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=\"n\">reporter</span> <span class=\"o\">=</span> <span class=\"n\">Reporters</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;Tintin&quot;</span><span class=\"p\">)</span>\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">update</span><span class=\"p\">(</span><span class=\"n\">stories_filed</span><span class=\"o\">=</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;stories_filed&quot;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>我们还可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.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\"><span class=\"pre\">update()</span></code></a> 来递增多个对象上的字段值——这可能比从数据库中把它们全部拉到 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=\"n\">Reporter</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">update</span><span class=\"p\">(</span><span class=\"n\">stories_filed</span><span class=\"o\">=</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;stories_filed&quot;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>因此，<code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 可以通过以下方式提供性能优势：</p>\n<ul class=\"simple\">\n<li><p>让数据库，而不是 Python 来完成工作</p></li>\n<li><p>减少某些操作所需的查询次数</p></li>\n</ul>\n<section id=\"slicing-f-expressions\">\n<span id=\"slicing-using-f\"></span><h4>切片 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 表达式<a class=\"heading-anchor\" href=\"#slicing-f-expressions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<aside class=\"version-note version-added\" data-version=\"5.1\">\n<p class=\"version-note-title\">New in Django 5.1</p></aside>\n<p>对于基于字符串的字段、基于文本的字段和 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/contrib/postgres/fields/#django.contrib.postgres.fields.ArrayField\" title=\"django.contrib.postgres.fields.ArrayField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ArrayField</span></code></a>，你可以使用 Python 的数组切片语法。索引从 0 开始，并且不支持 <code class=\"docutils literal notranslate\"><span class=\"pre\">slice</span></code> 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">step</span></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><span class=\"c1\"># Replacing a name with a substring of itself.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">writer</span> <span class=\"o\">=</span> <span class=\"n\">Writers</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;Priyansh&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">writer</span><span class=\"o\">.</span><span class=\"n\">name</span> <span class=\"o\">=</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">)[</span><span class=\"mi\">1</span><span class=\"p\">:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">writer</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">writer</span><span class=\"o\">.</span><span class=\"n\">refresh_from_db</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">writer</span><span class=\"o\">.</span><span class=\"n\">name</span>\n<span class=\"go\">&#39;riya&#39;</span>\n</code></pre></div>\n</section>\n<section id=\"avoiding-race-conditions-using-f\">\n<span id=\"id2\"></span><h4>使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 避免竞争条件<a class=\"heading-anchor\" href=\"#avoiding-race-conditions-using-f\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 的另一个有用的好处是，让数据库——而不是 Python——更新一个字段的值，避免了 <em>竞争条件</em>。</p>\n<p>如果两个 Python 线程执行上面第一个例子中的代码，一个线程可以在另一个线程从数据库中获取一个字段的值后，检索、递增并保存它。第二个线程保存的值将基于原始值，第一个线程的工作将丢失。</p>\n<p>如果数据库负责更新字段，那么这个过程就比较稳健：它只会在执行 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/instances/#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">save()</span></code></a> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">update()</span></code> 时，根据数据库中字段的值来更新字段，而不是根据检索实例时的值来更新。</p>\n</section>\n<section id=\"f-assignments-persist-after-model-save\">\n<h4><code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 赋值在 <code class=\"docutils literal notranslate\"><span class=\"pre\">Model.save()</span></code> 之后持续存在<a class=\"heading-anchor\" href=\"#f-assignments-persist-after-model-save\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 分配给模型字段的对象在保存模型实例后会持续存在，并将应用于每个 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/instances/#django.db.models.Model.save\" title=\"django.db.models.Model.save\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">save()</span></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=\"n\">reporter</span> <span class=\"o\">=</span> <span class=\"n\">Reporters</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;Tintin&quot;</span><span class=\"p\">)</span>\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">stories_filed</span> <span class=\"o\">=</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;stories_filed&quot;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"mi\">1</span>\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;Tintin Jr.&quot;</span>\n<span class=\"n\">reporter</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>在这种情况下，<code class=\"docutils literal notranslate\"><span class=\"pre\">stories_filed</span></code> 将被更新两次。如果最初是 <code class=\"docutils literal notranslate\"><span class=\"pre\">1</span></code>，最终值将是 <code class=\"docutils literal notranslate\"><span class=\"pre\">3</span></code>。这种持久性可以通过在保存模型对象后重新加载来避免，例如，使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/instances/#django.db.models.Model.refresh_from_db\" title=\"django.db.models.Model.refresh_from_db\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">refresh_from_db()</span></code></a>。</p>\n</section>\n<section id=\"using-f-in-filters\">\n<h4>在过滤器中使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code><a class=\"heading-anchor\" href=\"#using-f-in-filters\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 在 <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> 过滤器中也非常有用，它们可以根据对象的字段值而不是 Python 值的标准来过滤一组对象。</p>\n<p>这在 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/db/queries/#using-f-expressions-in-filters\"><span class=\"std std-ref\">在查询中使用 F() 表达式</span></a> 中有所记载。</p>\n</section>\n<section id=\"using-f-with-annotations\">\n<span id=\"id3\"></span><h4>与注解一起使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code><a class=\"heading-anchor\" href=\"#using-f-with-annotations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 可用于通过将不同的字段与算术相结合，在你的模型上创建动态字段：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">company</span> <span class=\"o\">=</span> <span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">chairs_needed</span><span class=\"o\">=</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_employees&quot;</span><span class=\"p\">)</span> <span class=\"o\">-</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_chairs&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>如果要组合的字段类型不同，您需要告诉 Django 返回什么类型的字段。大多数表达式都支持 <a class=\"reference internal\" href=\"#output-field\"><span class=\"std std-ref\">output_field</span></a> 用于此情况，但由于 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 不支持，您需要使用 <a class=\"reference internal\" href=\"#django.db.models.ExpressionWrapper\" title=\"django.db.models.ExpressionWrapper\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ExpressionWrapper</span></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=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">DateTimeField</span><span class=\"p\">,</span> <span class=\"n\">ExpressionWrapper</span><span class=\"p\">,</span> <span class=\"n\">F</span>\n\n<span class=\"n\">Ticket</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span>\n    <span class=\"n\">expires</span><span class=\"o\">=</span><span class=\"n\">ExpressionWrapper</span><span class=\"p\">(</span>\n        <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;active_at&quot;</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;duration&quot;</span><span class=\"p\">),</span> <span class=\"n\">output_field</span><span class=\"o\">=</span><span class=\"n\">DateTimeField</span><span class=\"p\">()</span>\n    <span class=\"p\">)</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>在引用关系字段（如 <code class=\"docutils literal notranslate\"><span class=\"pre\">ForeignKey</span></code>）时，<code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></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><span class=\"n\">car</span> <span class=\"o\">=</span> <span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">built_by</span><span class=\"o\">=</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;manufacturer&quot;</span><span class=\"p\">))[</span><span class=\"mi\">0</span><span class=\"p\">]</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">car</span><span class=\"o\">.</span><span class=\"n\">manufacturer</span>\n<span class=\"go\">&lt;Manufacturer: Toyota&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">car</span><span class=\"o\">.</span><span class=\"n\">built_by</span>\n<span class=\"go\">3</span>\n</code></pre></div>\n</section>\n<section id=\"using-f-to-sort-null-values\">\n<span id=\"id4\"></span><h4>使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 对空值进行排序<a class=\"heading-anchor\" href=\"#using-f-to-sort-null-values\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 和 <a class=\"reference internal\" href=\"#django.db.models.Expression.asc\" title=\"django.db.models.Expression.asc\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Expression.asc()</span></code></a> 或 <code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">esc()</span></code> 的关键词参数 <code class=\"docutils literal notranslate\"><span class=\"pre\">nulls_first</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">nulls_last</span></code> 来控制字段的空值的排序。默认情况下，排序取决于你的数据库。</p>\n<p>例如，在已经联系过的公司之后，对尚未联系过的公司进行排序（<code class=\"docutils literal notranslate\"><span class=\"pre\">last_contacted</span></code> 为空）：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">F</span>\n\n<span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;last_contacted&quot;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">desc</span><span class=\"p\">(</span><span class=\"n\">nulls_last</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">))</span>\n</code></pre></div>\n</section>\n<section id=\"using-f-with-logical-operations\">\n<h4>使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 进行逻辑操作<a class=\"heading-anchor\" href=\"#using-f-with-logical-operations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 表达式输出 <code class=\"docutils literal notranslate\"><span class=\"pre\">BooleanField</span></code> 的情况下，可以使用反转运算符 <code class=\"docutils literal notranslate\"><span class=\"pre\">~F()</span></code> 进行逻辑否定。例如，要交换公司的激活状态：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">F</span>\n\n<span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">update</span><span class=\"p\">(</span><span class=\"n\">is_active</span><span class=\"o\">=~</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;is_active&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"func-expressions\">\n<span id=\"id5\"></span><h3><code class=\"docutils literal notranslate\"><span class=\"pre\">Func()</span></code> 表达式<a class=\"heading-anchor\" href=\"#func-expressions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">Func()</span></code> 表达式是所有涉及 <code class=\"docutils literal notranslate\"><span class=\"pre\">COALESCE</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">LOWER</span></code> 等数据库函数或 <code class=\"docutils literal notranslate\"><span class=\"pre\">SUM</span></code> 等集合的表达式的基本类型。它们可以直接使用：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">F</span><span class=\"p\">,</span> <span class=\"n\">Func</span>\n\n<span class=\"n\">queryset</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">field_lower</span><span class=\"o\">=</span><span class=\"n\">Func</span><span class=\"p\">(</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;field&quot;</span><span class=\"p\">),</span> <span class=\"n\">function</span><span class=\"o\">=</span><span class=\"s2\">&quot;LOWER&quot;</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=\"w\"> </span><span class=\"nc\">Lower</span><span class=\"p\">(</span><span class=\"n\">Func</span><span class=\"p\">):</span>\n    <span class=\"n\">function</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;LOWER&quot;</span>\n\n\n<span class=\"n\">queryset</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">field_lower</span><span class=\"o\">=</span><span class=\"n\">Lower</span><span class=\"p\">(</span><span class=\"s2\">&quot;field&quot;</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>但这两种情况都会产生一个查询集，其中每个模型都有一个额外的属性 <code class=\"docutils literal notranslate\"><span class=\"pre\">field_lower</span></code> 来注释，大致由以下 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>\n<span class=\"w\">    </span><span class=\"p\">...</span>\n<span class=\"w\">    </span><span class=\"k\">LOWER</span><span class=\"p\">(</span><span class=\"ss\">&quot;db_table&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;field&quot;</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">as</span><span class=\"w\"> </span><span class=\"ss\">&quot;field_lower&quot;</span>\n</code></pre></div>\n<p>参见 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/database-functions/\"><span class=\"doc\">数据库函数</span></a> 获取内置的数据库函数列表。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">Func</span></code> API 如下：</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Func\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Func</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">*</span></span><span class=\"n\"><span class=\"pre\">expressions</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Func\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Func.function\">\n<span class=\"sig-name descname\"><span class=\"pre\">function</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Func.function\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>描述将要生成的函数的类属性。具体来说，<code class=\"docutils literal notranslate\"><span class=\"pre\">function</span></code> 将作为 <code class=\"docutils literal notranslate\"><span class=\"pre\">function</span></code> 占位符插在 <a class=\"reference internal\" href=\"#django.db.models.Func.template\" title=\"django.db.models.Func.template\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">template</span></code></a> 中。默认值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Func.template\">\n<span class=\"sig-name descname\"><span class=\"pre\">template</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Func.template\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个类属性，作为格式字符串，描述为该函数生成的SQL。默认值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">'%(function)s(%(expressions)s)'</span></code>。</p>\n<p>如果你正在构造像 <code class=\"docutils literal notranslate\"><span class=\"pre\">strftime('%W',</span> <span class=\"pre\">'date')</span></code> 这样的 SQL，并且需要在查询中使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">%</span></code> 字符，那么在 <code class=\"docutils literal notranslate\"><span class=\"pre\">template</span></code> 属性中把它四倍（<code class=\"docutils literal notranslate\"><span class=\"pre\">%%%%</span></code>），因为这个字符串会被插值两次：一次是在 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql()</span></code> 中的模板插值中，另一次是在数据库游标中的查询参数的 SQL 插值中。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Func.arg_joiner\">\n<span class=\"sig-name descname\"><span class=\"pre\">arg_joiner</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Func.arg_joiner\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个类属性，表示用于将 <code class=\"docutils literal notranslate\"><span class=\"pre\">expressions</span></code> 列表连接在一起的字符。默认值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">',</span> <span class=\"pre\">'</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Func.arity\">\n<span class=\"sig-name descname\"><span class=\"pre\">arity</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Func.arity\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个类属性，表示函数接受的参数数。如果设置了这个属性，并且用不同数量的表达式调用函数，将引发 <code class=\"docutils literal notranslate\"><span class=\"pre\">TypeError</span></code>。默认值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Func.as_sql\">\n<span class=\"sig-name descname\"><span class=\"pre\">as_sql</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">compiler</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">connection</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">function</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">template</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">arg_joiner</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra_context</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Func.as_sql\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>生成数据库函数的 SQL 片段。返回一个元组 <code class=\"docutils literal notranslate\"><span class=\"pre\">(sql,</span> <span class=\"pre\">params)</span></code>，其中 <code class=\"docutils literal notranslate\"><span class=\"pre\">sql</span></code> 是 SQL 字符串，<code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> 是查询参数的列表或元组。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">as_vendor()</span></code> 方法应该使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">function</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">template</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">arg_joiner</span></code> 以及其他 <code class=\"docutils literal notranslate\"><span class=\"pre\">**extra_context</span></code> 参数来根据需要定制 SQL。例如：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">django/db/models/functions.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">ConcatPair</span><span class=\"p\">(</span><span class=\"n\">Func</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n    <span class=\"n\">function</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;CONCAT&quot;</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">as_mysql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">extra_context</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">as_sql</span><span class=\"p\">(</span>\n            <span class=\"n\">compiler</span><span class=\"p\">,</span>\n            <span class=\"n\">connection</span><span class=\"p\">,</span>\n            <span class=\"n\">function</span><span class=\"o\">=</span><span class=\"s2\">&quot;CONCAT_WS&quot;</span><span class=\"p\">,</span>\n            <span class=\"n\">template</span><span class=\"o\">=</span><span class=\"s2\">&quot;</span><span class=\"si\">%(function)s</span><span class=\"s2\">(&#39;&#39;, </span><span class=\"si\">%(expressions)s</span><span class=\"s2\">)&quot;</span><span class=\"p\">,</span>\n            <span class=\"o\">**</span><span class=\"n\">extra_context</span>\n        <span class=\"p\">)</span>\n</code></pre></figure>\n<p>为了避免 SQL 注入漏洞，<code class=\"docutils literal notranslate\"><span class=\"pre\">extra_context</span></code> <a class=\"reference internal\" href=\"#avoiding-sql-injection-in-query-expressions\"><span class=\"std std-ref\">不得包含不受信任的用户输入</span></a>，因为这些值会被内插到 SQL 字符串中，而不是作为查询参数传递，数据库驱动对其进行转义。</p>\n</dd></dl>\n\n</dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">*expressions</span></code> 参数是一个位置表达式的列表，该函数将应用于此。表达式将被转换为字符串，用 <code class=\"docutils literal notranslate\"><span class=\"pre\">arg_joiner</span></code> 连接在一起，然后插入到 <code class=\"docutils literal notranslate\"><span class=\"pre\">template</span></code> 中作为 <code class=\"docutils literal notranslate\"><span class=\"pre\">expressions</span></code> 占位符。</p>\n<p>位置参数可以是表达式或 Python 值。字符串被认为是列引用，将被包装在 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 表达式中，而其他值将被包装在 <code class=\"docutils literal notranslate\"><span class=\"pre\">Value()</span></code> 表达式中。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">**extra</span></code> 关键字是 <code class=\"docutils literal notranslate\"><span class=\"pre\">key=value</span></code> 对，可以内插到 <code class=\"docutils literal notranslate\"><span class=\"pre\">template</span></code> 属性中。为了避免 SQL 注入漏洞，<code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> <a class=\"reference internal\" href=\"#avoiding-sql-injection-in-query-expressions\"><span class=\"std std-ref\">不能包含不受信任的用户输入</span></a>，因为这些值会被内插到 SQL 字符串中，而不是作为查询参数传递，数据库驱动程序对其进行转义。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">function</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">template</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">arg_joiner</span></code> 关键字可用于替换具有相同名称的属性，而无需定义自己的类。<a class=\"reference internal\" href=\"#output-field\"><span class=\"std std-ref\">output_field</span></a> 可用于定义预期的返回类型。</p>\n</section>\n<section id=\"aggregate-expressions\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">Aggregate()</span></code> 表达式<a class=\"heading-anchor\" href=\"#aggregate-expressions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>聚合表达式是 <a class=\"reference internal\" href=\"#func-expressions\"><span class=\"std std-ref\">Func() 表达式</span></a> 的一个特例，它通知查询需要一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">GROUP</span> <span class=\"pre\">BY</span></code> 子句。所有的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/querysets/#aggregation-functions\"><span class=\"std std-ref\">聚合函数</span></a>，如 <code class=\"docutils literal notranslate\"><span class=\"pre\">Sum()</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">Count()</span></code>，都继承自 <code class=\"docutils literal notranslate\"><span class=\"pre\">Aggregate()</span></code>。</p>\n<p>由于 <code class=\"docutils literal notranslate\"><span class=\"pre\">Aggregate</span></code> 是表达式和封装表达式，你可以表示一些复杂的计算：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Count</span>\n\n<span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span>\n    <span class=\"n\">managers_required</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"n\">Count</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_employees&quot;</span><span class=\"p\">)</span> <span class=\"o\">/</span> <span class=\"mi\">4</span><span class=\"p\">)</span> <span class=\"o\">+</span> <span class=\"n\">Count</span><span class=\"p\">(</span><span class=\"s2\">&quot;num_managers&quot;</span><span class=\"p\">)</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">Aggregate</span></code> 的 API 如下：</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Aggregate\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Aggregate</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">*</span></span><span class=\"n\"><span class=\"pre\">expressions</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">output_field</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">distinct</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">filter</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">default</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Aggregate\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Aggregate.template\">\n<span class=\"sig-name descname\"><span class=\"pre\">template</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Aggregate.template\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>作为格式字符串的类属性，描述为该集合生成的 SQL。默认值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">'%(function)s(%(distinct)s%(expressions)s)'</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Aggregate.function\">\n<span class=\"sig-name descname\"><span class=\"pre\">function</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Aggregate.function\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>描述将生成的集合函数的类属性。具体来说，<code class=\"docutils literal notranslate\"><span class=\"pre\">function</span></code> 将作为 <code class=\"docutils literal notranslate\"><span class=\"pre\">function</span></code> 占位符插值在 <a class=\"reference internal\" href=\"#django.db.models.Aggregate.template\" title=\"django.db.models.Aggregate.template\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">template</span></code></a> 中。默认值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Aggregate.window_compatible\">\n<span class=\"sig-name descname\"><span class=\"pre\">window_compatible</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Aggregate.window_compatible\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，因为大多数聚合函数可以作为 <a class=\"reference internal\" href=\"#django.db.models.expressions.Window\" title=\"django.db.models.expressions.Window\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Window</span></code></a> 中的源表达式。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Aggregate.allow_distinct\">\n<span class=\"sig-name descname\"><span class=\"pre\">allow_distinct</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Aggregate.allow_distinct\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个类属性，决定该聚合函数是否允许传递 <code class=\"docutils literal notranslate\"><span class=\"pre\">distinct</span></code> 关键字参数。如果设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> （默认），如果传递了 <code class=\"docutils literal notranslate\"><span class=\"pre\">distinct=True</span></code>，会引发 <code class=\"docutils literal notranslate\"><span class=\"pre\">TypeError</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Aggregate.empty_result_set_value\">\n<span class=\"sig-name descname\"><span class=\"pre\">empty_result_set_value</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Aggregate.empty_result_set_value\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>，因为大多数聚合函数在应用于空结果集时会产生 <code class=\"docutils literal notranslate\"><span class=\"pre\">NULL</span></code>。</p>\n</dd></dl>\n\n</dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">expressions</span></code> 的位置参数可以包括表达式、模型字段的转换或模型字段的名称。它们将被转换为字符串，并用作 <code class=\"docutils literal notranslate\"><span class=\"pre\">template</span></code> 中的 <code class=\"docutils literal notranslate\"><span class=\"pre\">expressions</span></code> 占位符。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">distinct</span></code> 参数决定是否应该为 <code class=\"docutils literal notranslate\"><span class=\"pre\">expressions</span></code> 的每一个不同的值（或一组值，对于多个 <code class=\"docutils literal notranslate\"><span class=\"pre\">expressions</span></code>）调用聚合函数。该参数仅在 <a class=\"reference internal\" href=\"#django.db.models.Aggregate.allow_distinct\" title=\"django.db.models.Aggregate.allow_distinct\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">allow_distinct</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 的聚合函数中得到支持。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">filter</span></code> 参数取一个 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/querysets/#django.db.models.Q\" title=\"django.db.models.Q\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Q</span> <span class=\"pre\">对象</span></code></a>，用于过滤被聚合的行。参见 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/conditional-expressions/#conditional-aggregation\"><span class=\"std std-ref\">条件聚合</span></a> 和 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/db/aggregation/#filtering-on-annotations\"><span class=\"std std-ref\">过滤注解</span></a> 的用法示例。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> 参数接受一个值，该值将与聚合一起传递给 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/database-functions/#django.db.models.functions.Coalesce\" title=\"django.db.models.functions.Coalesce\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Coalesce</span></code></a>。这对于指定在查询集（或分组）不包含条目时要返回的值非常有用，而不是返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">**extra</span></code> 关键字是 <code class=\"docutils literal notranslate\"><span class=\"pre\">key=value</span></code> 对，可以内插到 <code class=\"docutils literal notranslate\"><span class=\"pre\">template</span></code> 属性中。</p>\n</section>\n<section id=\"creating-your-own-aggregate-functions\">\n<h3>创建你自己的聚合函数<a class=\"heading-anchor\" href=\"#creating-your-own-aggregate-functions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你也可以创建自己的聚合函数。至少，你需要定义 <code class=\"docutils literal notranslate\"><span class=\"pre\">function</span></code>，但你也可以完全自定义生成的 SQL。下面是一个简单的例子：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Aggregate</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Sum</span><span class=\"p\">(</span><span class=\"n\">Aggregate</span><span class=\"p\">):</span>\n    <span class=\"c1\"># Supports SUM(ALL field).</span>\n    <span class=\"n\">function</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;SUM&quot;</span>\n    <span class=\"n\">template</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;</span><span class=\"si\">%(function)s</span><span class=\"s2\">(</span><span class=\"si\">%(all_values)s%(expressions)s</span><span class=\"s2\">)&quot;</span>\n    <span class=\"n\">allow_distinct</span> <span class=\"o\">=</span> <span class=\"kc\">False</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">expression</span><span class=\"p\">,</span> <span class=\"n\">all_values</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">extra</span><span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"n\">expression</span><span class=\"p\">,</span> <span class=\"n\">all_values</span><span class=\"o\">=</span><span class=\"s2\">&quot;ALL &quot;</span> <span class=\"k\">if</span> <span class=\"n\">all_values</span> <span class=\"k\">else</span> <span class=\"s2\">&quot;&quot;</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">extra</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"value-expressions\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">Value()</span></code> 表达式<a class=\"heading-anchor\" href=\"#value-expressions\"><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.Value\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Value</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">value</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">output_field</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Value\"><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\"><span class=\"pre\">Value()</span></code> 对象表示一个表达式中最小的成分：一个简单的值。当你需要在一个表达式中表示一个整数、布尔值或字符串的值时，你可以将该值包裹在一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Value()</span></code> 中。</p>\n<p>你很少会需要直接使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">Value()</span></code>。当你写下表达式 <code class=\"docutils literal notranslate\"><span class=\"pre\">F('field')</span> <span class=\"pre\">+</span> <span class=\"pre\">1</span></code> 时，Django 会隐式地将 <code class=\"docutils literal notranslate\"><span class=\"pre\">1</span></code> 包裹在 <code class=\"docutils literal notranslate\"><span class=\"pre\">Value()</span></code> 中，允许简单的值被用于更复杂的表达式中。当你想把一个字符串传递给一个表达式时，你需要使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">Value()</span></code>。大多数表达式将字符串参数解释为字段的名称，如 <code class=\"docutils literal notranslate\"><span class=\"pre\">Lower('name')</span></code>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">value</span></code> 参数描述了要包含在表达式中的值，比如 <code class=\"docutils literal notranslate\"><span class=\"pre\">1</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>。Django 知道如何将这些 Python 值转换为相应的数据库类型。</p>\n<p>如果没有指定 <a class=\"reference internal\" href=\"#output-field\"><span class=\"std std-ref\">output_field</span></a>，则对于许多常见类型，它将从提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">value</span></code> 的类型推断出来。例如，将 <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#datetime.datetime\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">datetime.datetime</span></code></a> 的实例作为 <code class=\"docutils literal notranslate\"><span class=\"pre\">value</span></code> 传递将默认 <code class=\"docutils literal notranslate\"><span class=\"pre\">output_field</span></code> 为 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a>。</p>\n</section>\n<section id=\"expressionwrapper-expressions\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">ExpressionWrapper()</span></code> 表达式<a class=\"heading-anchor\" href=\"#expressionwrapper-expressions\"><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.ExpressionWrapper\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">ExpressionWrapper</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expression</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">output_field</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.ExpressionWrapper\"><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\"><span class=\"pre\">ExpressionWrapper</span></code> 包围另一个表达式，并提供了访问属性的功能，例如 <a class=\"reference internal\" href=\"#output-field\"><span class=\"std std-ref\">output_field</span></a>，这些属性可能在其他表达式上不可用。在使用描述中不同类型的 <code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 表达式进行算术运算时，必须使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">ExpressionWrapper</span></code>，如 <a class=\"reference internal\" href=\"#using-f-with-annotations\"><span class=\"std std-ref\">与注解一起使用 F()</span></a> 中所述。</p>\n</section>\n<section id=\"conditional-expressions\">\n<h3>条件表达式<a class=\"heading-anchor\" href=\"#conditional-expressions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\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\"><span class=\"pre\">if</span></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\"><span class=\"pre\">elif</span></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\"><span class=\"pre\">else</span></code></a> 逻辑。Django 原生支持 SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">CASE</span></code> 表达式。更多细节请参见 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/conditional-expressions/\"><span class=\"doc\">条件表达式</span></a>。</p>\n</section>\n<section id=\"subquery-expressions\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery()</span></code> 表达式<a class=\"heading-anchor\" href=\"#subquery-expressions\"><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.Subquery\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Subquery</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">queryset</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">output_field</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Subquery\"><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\"><span class=\"pre\">Subquery</span></code> 表达式向 <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> 添加一个显式子查询。</p>\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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">OuterRef</span><span class=\"p\">,</span> <span class=\"n\">Subquery</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">newest</span> <span class=\"o\">=</span> <span class=\"n\">Comment</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">post</span><span class=\"o\">=</span><span class=\"n\">OuterRef</span><span class=\"p\">(</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">))</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s2\">&quot;-created_at&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Post</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">newest_commenter_email</span><span class=\"o\">=</span><span class=\"n\">Subquery</span><span class=\"p\">(</span><span class=\"n\">newest</span><span class=\"o\">.</span><span class=\"n\">values</span><span class=\"p\">(</span><span class=\"s2\">&quot;email&quot;</span><span class=\"p\">)[:</span><span class=\"mi\">1</span><span class=\"p\">]))</span>\n</code></pre></div>\n<p>在 PostgreSQL 上，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=\"w\"> </span><span class=\"ss\">&quot;post&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;id&quot;</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">    </span><span class=\"k\">SELECT</span><span class=\"w\"> </span><span class=\"n\">U0</span><span class=\"p\">.</span><span class=\"ss\">&quot;email&quot;</span>\n<span class=\"w\">    </span><span class=\"k\">FROM</span><span class=\"w\"> </span><span class=\"ss\">&quot;comment&quot;</span><span class=\"w\"> </span><span class=\"n\">U0</span>\n<span class=\"w\">    </span><span class=\"k\">WHERE</span><span class=\"w\"> </span><span class=\"n\">U0</span><span class=\"p\">.</span><span class=\"ss\">&quot;post_id&quot;</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"ss\">&quot;post&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;id&quot;</span><span class=\"p\">)</span>\n<span class=\"w\">    </span><span class=\"k\">ORDER</span><span class=\"w\"> </span><span class=\"k\">BY</span><span class=\"w\"> </span><span class=\"n\">U0</span><span class=\"p\">.</span><span class=\"ss\">&quot;created_at&quot;</span><span class=\"w\"> </span><span class=\"k\">DESC</span><span class=\"w\"> </span><span class=\"k\">LIMIT</span><span class=\"w\"> </span><span class=\"mi\">1</span>\n<span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">AS</span><span class=\"w\"> </span><span class=\"ss\">&quot;newest_commenter_email&quot;</span><span class=\"w\"> </span><span class=\"k\">FROM</span><span class=\"w\"> </span><span class=\"ss\">&quot;post&quot;</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>本节中的例子是为了展示如何强制 Django 执行一个子查询。在某些情况下，可以写一个等价的查询集，更清楚或更有效地执行同样的任务。</p>\n</aside>\n<section id=\"referencing-columns-from-the-outer-queryset\">\n<h4>从外部查询集中引用列<a class=\"heading-anchor\" href=\"#referencing-columns-from-the-outer-queryset\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.OuterRef\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">OuterRef</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">field</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.OuterRef\"><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\"><span class=\"pre\">Subquery</span></code> 中的查询集需要引用外部查询或其转换的字段时，请使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">OuterRef</span></code>。它的行为类似于 <a class=\"reference internal\" href=\"#django.db.models.F\" title=\"django.db.models.F\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">F</span></code></a> 表达式，不同之处在于检查是否引用有效字段的操作直到外部查询被解析时才会执行。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">OuterRef</span></code> 的实例可以与嵌套的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery</span></code> 的实例结合使用，以引用不是直接父级的包含查询集。例如，为了正确解析此查询集，它需要在嵌套的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery</span></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><span class=\"n\">Book</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">author</span><span class=\"o\">=</span><span class=\"n\">OuterRef</span><span class=\"p\">(</span><span class=\"n\">OuterRef</span><span class=\"p\">(</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">)))</span>\n</code></pre></div>\n</section>\n<section id=\"limiting-a-subquery-to-a-single-column\">\n<h4>将子查询限制为单列<a class=\"heading-anchor\" href=\"#limiting-a-subquery-to-a-single-column\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>有时需要从 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery</span></code> 返回单个列，例如，将 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery</span></code> 用作 <code class=\"docutils literal notranslate\"><span class=\"pre\">__in</span></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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">datetime</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timedelta</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">one_day_ago</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span> <span class=\"o\">-</span> <span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">posts</span> <span class=\"o\">=</span> <span class=\"n\">Post</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">published_at__gte</span><span class=\"o\">=</span><span class=\"n\">one_day_ago</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Comment</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">post__in</span><span class=\"o\">=</span><span class=\"n\">Subquery</span><span class=\"p\">(</span><span class=\"n\">posts</span><span class=\"o\">.</span><span class=\"n\">values</span><span class=\"p\">(</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">)))</span>\n</code></pre></div>\n<p>在这种情况下，子查询必须使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.values\" title=\"django.db.models.query.QuerySet.values\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">values()</span></code></a> 只返回一列：该文章的主键。</p>\n</section>\n<section id=\"limiting-the-subquery-to-a-single-row\">\n<h4>将子查询限制为单行<a class=\"heading-anchor\" href=\"#limiting-the-subquery-to-a-single-row\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>为了防止子查询返回多行，使用了查询集的切片（<code class=\"docutils literal notranslate\"><span class=\"pre\">[:1]</span></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><span class=\"n\">subquery</span> <span class=\"o\">=</span> <span class=\"n\">Subquery</span><span class=\"p\">(</span><span class=\"n\">newest</span><span class=\"o\">.</span><span class=\"n\">values</span><span class=\"p\">(</span><span class=\"s2\">&quot;email&quot;</span><span class=\"p\">)[:</span><span class=\"mi\">1</span><span class=\"p\">])</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Post</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">newest_commenter_email</span><span class=\"o\">=</span><span class=\"n\">subquery</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>在这种情况下，子查询必须只返回一列 <em>和</em> 一行：最近创建的评论的电子邮件地址。</p>\n<p>（使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a> 而不是分片会导致失败，因为 <code class=\"docutils literal notranslate\"><span class=\"pre\">OuterRef</span></code> 在 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery</span></code> 中使用查询集之前无法解析。)</p>\n</section>\n<section id=\"exists-subqueries\">\n<h4><code class=\"docutils literal notranslate\"><span class=\"pre\">Exists()</span></code> 子查询<a class=\"heading-anchor\" href=\"#exists-subqueries\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Exists\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Exists</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">queryset</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Exists\"><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\"><span class=\"pre\">Exists</span></code> 是一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery</span></code> 子类，它使用 SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">EXISTS</span></code> 语句。在许多情况下，它的性能比子查询更好，因为当找到第一条匹配的记录时，数据库能够停止对子查询的执行。</p>\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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Exists</span><span class=\"p\">,</span> <span class=\"n\">OuterRef</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">datetime</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timedelta</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">one_day_ago</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span> <span class=\"o\">-</span> <span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">recent_comments</span> <span class=\"o\">=</span> <span class=\"n\">Comment</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">post</span><span class=\"o\">=</span><span class=\"n\">OuterRef</span><span class=\"p\">(</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>    <span class=\"n\">created_at__gte</span><span class=\"o\">=</span><span class=\"n\">one_day_ago</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Post</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">recent_comment</span><span class=\"o\">=</span><span class=\"n\">Exists</span><span class=\"p\">(</span><span class=\"n\">recent_comments</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>在 PostgreSQL 上，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=\"w\"> </span><span class=\"ss\">&quot;post&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;id&quot;</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"ss\">&quot;post&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;published_at&quot;</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"k\">EXISTS</span><span class=\"p\">(</span>\n<span class=\"w\">    </span><span class=\"k\">SELECT</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">as</span><span class=\"w\"> </span><span class=\"ss\">&quot;a&quot;</span>\n<span class=\"w\">    </span><span class=\"k\">FROM</span><span class=\"w\"> </span><span class=\"ss\">&quot;comment&quot;</span><span class=\"w\"> </span><span class=\"n\">U0</span>\n<span class=\"w\">    </span><span class=\"k\">WHERE</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">        </span><span class=\"n\">U0</span><span class=\"p\">.</span><span class=\"ss\">&quot;created_at&quot;</span><span class=\"w\"> </span><span class=\"o\">&gt;=</span><span class=\"w\"> </span><span class=\"n\">YYYY</span><span class=\"o\">-</span><span class=\"n\">MM</span><span class=\"o\">-</span><span class=\"n\">DD</span><span class=\"w\"> </span><span class=\"n\">HH</span><span class=\"p\">:</span><span class=\"n\">MM</span><span class=\"p\">:</span><span class=\"n\">SS</span><span class=\"w\"> </span><span class=\"k\">AND</span>\n<span class=\"w\">        </span><span class=\"n\">U0</span><span class=\"p\">.</span><span class=\"ss\">&quot;post_id&quot;</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"ss\">&quot;post&quot;</span><span class=\"p\">.</span><span class=\"ss\">&quot;id&quot;</span>\n<span class=\"w\">    </span><span class=\"p\">)</span>\n<span class=\"w\">    </span><span class=\"k\">LIMIT</span><span class=\"w\"> </span><span class=\"mi\">1</span>\n<span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">AS</span><span class=\"w\"> </span><span class=\"ss\">&quot;recent_comment&quot;</span><span class=\"w\"> </span><span class=\"k\">FROM</span><span class=\"w\"> </span><span class=\"ss\">&quot;post&quot;</span>\n</code></pre></div>\n<p>没有必要强制 <code class=\"docutils literal notranslate\"><span class=\"pre\">Exists</span></code> 指向单一列，因为列会被丢弃，并返回一个布尔结果。同样，由于在 SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">EXISTS</span></code> 子查询中，排序并不重要，只会降低性能，所以会自动删除。</p>\n<p>可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">`~Exists()</span></code> 来查询 <code class=\"docutils literal notranslate\"><span class=\"pre\">NOT</span> <span class=\"pre\">EXISTS</span></code>。</p>\n</section>\n<section id=\"filtering-on-a-subquery-or-exists-expressions\">\n<h4>对 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery()</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">Exists()</span></code> 表达式进行过滤。<a class=\"heading-anchor\" href=\"#filtering-on-a-subquery-or-exists-expressions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>返回布尔值的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery()</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">Exists()</span></code> 可以用作 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/conditional-expressions/#django.db.models.expressions.When\" title=\"django.db.models.expressions.When\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">When</span></code></a> 表达式中的 <code class=\"docutils literal notranslate\"><span class=\"pre\">condition</span></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><span class=\"n\">recent_comments</span> <span class=\"o\">=</span> <span class=\"n\">Comment</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>  <span class=\"c1\"># From above</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Post</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">Exists</span><span class=\"p\">(</span><span class=\"n\">recent_comments</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>这将确保子查询不会被添加到 <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span></code> 列中，这可能会带来更好的性能。</p>\n</section>\n<section id=\"using-aggregates-within-a-subquery-expression\">\n<h4>在 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery</span></code> 表达式中使用集合。<a class=\"heading-anchor\" href=\"#using-aggregates-within-a-subquery-expression\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>聚合可以在 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery</span></code> 中使用，但需要将 <a class=\"reference internal\" href=\"/zh-hans/5.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\"><span class=\"pre\">filter()</span></code></a>、<a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.values\" title=\"django.db.models.query.QuerySet.values\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">values()</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.annotate\" title=\"django.db.models.query.QuerySet.annotate\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">annotate()</span></code></a> 进行特定的组合，才能使子查询分组正确。</p>\n<p>假设两个模型都有一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">length</span></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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">OuterRef</span><span class=\"p\">,</span> <span class=\"n\">Subquery</span><span class=\"p\">,</span> <span class=\"n\">Sum</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">comments</span> <span class=\"o\">=</span> <span class=\"n\">Comment</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">post</span><span class=\"o\">=</span><span class=\"n\">OuterRef</span><span class=\"p\">(</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">))</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">values</span><span class=\"p\">(</span><span class=\"s2\">&quot;post&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">total_comments</span> <span class=\"o\">=</span> <span class=\"n\">comments</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">total</span><span class=\"o\">=</span><span class=\"n\">Sum</span><span class=\"p\">(</span><span class=\"s2\">&quot;length&quot;</span><span class=\"p\">))</span><span class=\"o\">.</span><span class=\"n\">values</span><span class=\"p\">(</span><span class=\"s2\">&quot;total&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Post</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">length__gt</span><span class=\"o\">=</span><span class=\"n\">Subquery</span><span class=\"p\">(</span><span class=\"n\">total_comments</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>初始的 <code class=\"docutils literal notranslate\"><span class=\"pre\">filter(...)</span></code> 将子查询限制在相关参数上。<code class=\"docutils literal notranslate\"><span class=\"pre\">order_by()</span></code> 删除 <code class=\"docutils literal notranslate\"><span class=\"pre\">Comment</span></code> 模型上的默认 <code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">Order</span></code> （如果有的话）。<code class=\"docutils literal notranslate\"><span class=\"pre\">values('post')</span></code> 按 <code class=\"docutils literal notranslate\"><span class=\"pre\">Post</span></code> 聚合评论。最后，<code class=\"docutils literal notranslate\"><span class=\"pre\">annotate(...)</span></code> 执行聚合。这些查询集方法的应用顺序很重要。在这种情况下，由于子查询必须限于一列，所以需要使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">values('total')</span></code>。</p>\n<p>这是在 <code class=\"docutils literal notranslate\"><span class=\"pre\">Subquery</span></code> 内进行聚合的唯一方法，因为使用 <code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">aggregary()</span></code> 试图执行查询集（如果有 <code class=\"docutils literal notranslate\"><span class=\"pre\">OuterRef</span></code>，将无法解决）。</p>\n</section>\n</section>\n<section id=\"raw-sql-expressions\">\n<h3>原始 SQL 表达式<a class=\"heading-anchor\" href=\"#raw-sql-expressions\"><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.RawSQL\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">RawSQL</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sql</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">params</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">output_field</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.RawSQL\"><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\"><span class=\"pre\">WHERE</span></code> 子句。在这些特殊情况下，可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">RawSQL</span></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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models.expressions</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">RawSQL</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">queryset</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span><span class=\"n\">val</span><span class=\"o\">=</span><span class=\"n\">RawSQL</span><span class=\"p\">(</span><span class=\"s2\">&quot;select col from sometable where othercol = </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span> <span class=\"p\">(</span><span class=\"n\">param</span><span class=\"p\">,)))</span>\n</code></pre></div>\n<p>这些额外的查找可能无法移植到不同的数据库引擎中（因为你是显式地编写 SQL 代码），并且违反了 DRY 原则，所以你应该尽可能地避免它们。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">RawSQL</span></code> 表达式也可以用作 <code class=\"docutils literal notranslate\"><span class=\"pre\">__in</span></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><span class=\"n\">queryset</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">id__in</span><span class=\"o\">=</span><span class=\"n\">RawSQL</span><span class=\"p\">(</span><span class=\"s2\">&quot;select id from sometable where col = </span><span class=\"si\">%s</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span> <span class=\"p\">(</span><span class=\"n\">param</span><span class=\"p\">,)))</span>\n</code></pre></div>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>为了防止 <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/SQL_injection\">SQL 注入攻击</a> ，你必须使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> 来转义任何用户可以控制的参数。<code class=\"docutils literal notranslate\"><span class=\"pre\">params</span></code> 是一个必要的参数，以迫使你承认你没有用用户提供的数据来插值你的 SQL。</p>\n<p>你也不能在 SQL 字符串中引用占位符。这个例子由于在 <code class=\"docutils literal notranslate\"><span class=\"pre\">%s</span></code> 周围的引号而容易受到 SQL 注入：</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=\"n\">RawSQL</span><span class=\"p\">(</span><span class=\"s2\">&quot;select col from sometable where othercol = &#39;</span><span class=\"si\">%s</span><span class=\"s2\">&#39;&quot;</span><span class=\"p\">)</span>  <span class=\"c1\"># unsafe!</span>\n</code></pre></div>\n<p>你可以阅读更多关于 Django 的 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/security/#sql-injection-protection\"><span class=\"std std-ref\">SQL 注入保护</span></a> 的工作原理。</p>\n</aside>\n</section>\n<section id=\"window-functions\">\n<h3>窗口函数<a class=\"heading-anchor\" href=\"#window-functions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>窗口函数提供了一种在分区上应用函数的方法。与一般的聚合函数不同，窗口函数对 <a class=\"reference internal\" href=\"#window-frames\"><span class=\"std std-ref\">帧</span></a> 和分区进行操作，并计算每行的结果。</p>\n<p>你可以在同一个查询中指定多个窗口，这在 Django ORM 中相当于在一个 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/db/aggregation/\"><span class=\"doc\">QuerySet.annotate()</span></a> 调用中包含多个表达式。ORM 并没有利用命名窗口，而是将其作为所选列的一部分。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.Window\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Window</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expression</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">partition_by</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">order_by</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">frame</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">output_field</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.Window\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.Window.template\">\n<span class=\"sig-name descname\"><span class=\"pre\">template</span></span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.Window.template\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">%(expression)s</span> <span class=\"pre\">OVER</span> <span class=\"pre\">(%(window)s)</span></code>。如果只提供了 <code class=\"docutils literal notranslate\"><span class=\"pre\">expression</span></code> 参数，则窗口子句将为空。</p>\n</dd></dl>\n\n</dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">Window</span></code> 类是 <code class=\"docutils literal notranslate\"><span class=\"pre\">OVER</span></code> 子句的主要表达式。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">expression</span></code> 参数是一个 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/database-functions/#window-functions\"><span class=\"std std-ref\">窗口函数</span></a>，一个 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/querysets/#aggregation-functions\"><span class=\"std std-ref\">聚合函数</span></a>，或者一个与窗口子句兼容的表达式。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">partition_by</span></code> 参数接受一个表达式或一个表达式序列（列名应包装在 <code class=\"docutils literal notranslate\"><span class=\"pre\">F</span></code> 对象中），用于控制行的分区。分区将缩小用于计算结果集的行范围。</p>\n<p><a class=\"reference internal\" href=\"#output-field\"><span class=\"std std-ref\">output_field</span></a> 要么作为参数指定，要么由表达式指定。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">order_by</span></code> 参数接受一个表达式，您可以在该表达式上调用 <a class=\"reference internal\" href=\"#django.db.models.Expression.asc\" title=\"django.db.models.Expression.asc\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">asc()</span></code></a> 和 <a class=\"reference internal\" href=\"#django.db.models.Expression.desc\" title=\"django.db.models.Expression.desc\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">desc()</span></code></a>，一个字段名称的字符串（可以有可选的 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;-&quot;</span></code> 前缀，表示降序），或一个字符串和/或表达式的元组或列表。排序控制表达式应用的顺序。例如，如果在一个分区内对行进行求和，第一个结果是第一行的值，第二个结果是第一行和第二行的和。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">frame</span></code> 参数指定在计算中应该使用哪些其他行。详见 <a class=\"reference internal\" href=\"#window-frames\"><span class=\"std std-ref\">帧</span></a>。</p>\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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Avg</span><span class=\"p\">,</span> <span class=\"n\">F</span><span class=\"p\">,</span> <span class=\"n\">Window</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Movie</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">avg_rating</span><span class=\"o\">=</span><span class=\"n\">Window</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>        <span class=\"n\">expression</span><span class=\"o\">=</span><span class=\"n\">Avg</span><span class=\"p\">(</span><span class=\"s2\">&quot;rating&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>        <span class=\"n\">partition_by</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;studio&quot;</span><span class=\"p\">),</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;genre&quot;</span><span class=\"p\">)],</span>\n<span class=\"gp\">... </span>        <span class=\"n\">order_by</span><span class=\"o\">=</span><span class=\"s2\">&quot;released__year&quot;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    <span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n<p>这可以让你检查一部电影的评分是好是坏，与它的同行相比。</p>\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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Avg</span><span class=\"p\">,</span> <span class=\"n\">F</span><span class=\"p\">,</span> <span class=\"n\">Max</span><span class=\"p\">,</span> <span class=\"n\">Min</span><span class=\"p\">,</span> <span class=\"n\">Window</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">window</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n<span class=\"gp\">... </span>    <span class=\"s2\">&quot;partition_by&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;studio&quot;</span><span class=\"p\">),</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;genre&quot;</span><span class=\"p\">)],</span>\n<span class=\"gp\">... </span>    <span class=\"s2\">&quot;order_by&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;released__year&quot;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span><span class=\"p\">}</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Movie</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">avg_rating</span><span class=\"o\">=</span><span class=\"n\">Window</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>        <span class=\"n\">expression</span><span class=\"o\">=</span><span class=\"n\">Avg</span><span class=\"p\">(</span><span class=\"s2\">&quot;rating&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>        <span class=\"o\">**</span><span class=\"n\">window</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    <span class=\"p\">),</span>\n<span class=\"gp\">... </span>    <span class=\"n\">best</span><span class=\"o\">=</span><span class=\"n\">Window</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>        <span class=\"n\">expression</span><span class=\"o\">=</span><span class=\"n\">Max</span><span class=\"p\">(</span><span class=\"s2\">&quot;rating&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>        <span class=\"o\">**</span><span class=\"n\">window</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    <span class=\"p\">),</span>\n<span class=\"gp\">... </span>    <span class=\"n\">worst</span><span class=\"o\">=</span><span class=\"n\">Window</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>        <span class=\"n\">expression</span><span class=\"o\">=</span><span class=\"n\">Min</span><span class=\"p\">(</span><span class=\"s2\">&quot;rating&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>        <span class=\"o\">**</span><span class=\"n\">window</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    <span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n<p>对窗口函数进行过滤是支持的，只要查找不是不连续的（不使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">OR</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">XOR</span></code> 作为连接器）并且对执行聚合的查询集进行过滤。</p>\n<p>例如，依赖于聚合并具有针对窗口函数和字段的 <code class=\"docutils literal notranslate\"><span class=\"pre\">OR</span></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><span class=\"n\">qs</span> <span class=\"o\">=</span> <span class=\"n\">Movie</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">category_rank</span><span class=\"o\">=</span><span class=\"n\">Window</span><span class=\"p\">(</span><span class=\"n\">Rank</span><span class=\"p\">(),</span> <span class=\"n\">partition_by</span><span class=\"o\">=</span><span class=\"s2\">&quot;category&quot;</span><span class=\"p\">,</span> <span class=\"n\">order_by</span><span class=\"o\">=</span><span class=\"s2\">&quot;-rating&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>    <span class=\"n\">scenes_count</span><span class=\"o\">=</span><span class=\"n\">Count</span><span class=\"p\">(</span><span class=\"s2\">&quot;actors&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">Q</span><span class=\"p\">(</span><span class=\"n\">category_rank__lte</span><span class=\"o\">=</span><span class=\"mi\">3</span><span class=\"p\">)</span> <span class=\"o\">|</span> <span class=\"n\">Q</span><span class=\"p\">(</span><span class=\"n\">title__contains</span><span class=\"o\">=</span><span class=\"s2\">&quot;Batman&quot;</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"nb\">list</span><span class=\"p\">(</span><span class=\"n\">qs</span><span class=\"p\">)</span>\n<span class=\"go\">NotImplementedError: Heterogeneous disjunctive predicates against window functions</span>\n<span class=\"go\">are not implemented when performing conditional aggregation.</span>\n</code></pre></div>\n<p>在 Django 的内置数据库后端中，MySQL、PostgreSQL 和 Oracle 支持窗口表达式。不同数据库之间对窗口表达式功能的支持有所不同。例如， <a class=\"reference internal\" href=\"#django.db.models.Expression.asc\" title=\"django.db.models.Expression.asc\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">asc()</span></code></a> 和 <a class=\"reference internal\" href=\"#django.db.models.Expression.desc\" title=\"django.db.models.Expression.desc\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">desc()</span></code></a> 中的选项可能不被支持。根据需要，请查阅您数据库的文档。</p>\n<section id=\"frames\">\n<span id=\"window-frames\"></span><h4>帧<a class=\"heading-anchor\" href=\"#frames\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>对于一个窗口帧，你可以选择基于范围的行序列或普通的行序列。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.ValueRange\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">ValueRange</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">start</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">end</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">exclusion</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.ValueRange\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.ValueRange.frame_type\">\n<span class=\"sig-name descname\"><span class=\"pre\">frame_type</span></span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.ValueRange.frame_type\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>该属性被设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">'RANGE'</span></code>。</p>\n</dd></dl>\n\n<p>PostgreSQL 对 <code class=\"docutils literal notranslate\"><span class=\"pre\">ValueRange</span></code> 的支持有限，只支持使用标准的开始和结束点，如 <code class=\"docutils literal notranslate\"><span class=\"pre\">CURRENT</span> <span class=\"pre\">ROW</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">UNBOUNDED</span> <span class=\"pre\">FOLLOWING</span></code>。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">exclusion</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.RowRange\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">RowRange</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">start</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">end</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">exclusion</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.RowRange\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.RowRange.frame_type\">\n<span class=\"sig-name descname\"><span class=\"pre\">frame_type</span></span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.RowRange.frame_type\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>该属性被设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">'ROWS'</span></code>。</p>\n</dd></dl>\n\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">exclusion</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\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=\"o\">%</span><span class=\"p\">(</span><span class=\"n\">frame_type</span><span class=\"p\">)</span><span class=\"n\">s</span><span class=\"w\"> </span><span class=\"k\">BETWEEN</span><span class=\"w\"> </span><span class=\"o\">%</span><span class=\"p\">(</span><span class=\"k\">start</span><span class=\"p\">)</span><span class=\"n\">s</span><span class=\"w\"> </span><span class=\"k\">AND</span><span class=\"w\"> </span><span class=\"o\">%</span><span class=\"p\">(</span><span class=\"k\">end</span><span class=\"p\">)</span><span class=\"n\">s</span>\n</code></pre></div>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.WindowFrameExclusion\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">WindowFrameExclusion</span></span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.WindowFrameExclusion\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><aside class=\"version-note version-added\" data-version=\"5.1\">\n<p class=\"version-note-title\">New in Django 5.1</p></aside>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.WindowFrameExclusion.CURRENT_ROW\">\n<span class=\"sig-name descname\"><span class=\"pre\">CURRENT_ROW</span></span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.WindowFrameExclusion.CURRENT_ROW\"><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 attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.WindowFrameExclusion.GROUP\">\n<span class=\"sig-name descname\"><span class=\"pre\">GROUP</span></span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.WindowFrameExclusion.GROUP\"><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 attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.WindowFrameExclusion.TIES\">\n<span class=\"sig-name descname\"><span class=\"pre\">TIES</span></span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.WindowFrameExclusion.TIES\"><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 attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.expressions.WindowFrameExclusion.NO_OTHERS\">\n<span class=\"sig-name descname\"><span class=\"pre\">NO_OTHERS</span></span><a class=\"heading-anchor\" href=\"#django.db.models.expressions.WindowFrameExclusion.NO_OTHERS\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n</dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">exclusion</span></code> 参数允许在支持的数据库上从窗口框架中排除行 (<a class=\"reference internal\" href=\"#django.db.models.expressions.WindowFrameExclusion.CURRENT_ROW\" title=\"django.db.models.expressions.WindowFrameExclusion.CURRENT_ROW\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">CURRENT_ROW</span></code></a>)、组 (<a class=\"reference internal\" href=\"#django.db.models.expressions.WindowFrameExclusion.GROUP\" title=\"django.db.models.expressions.WindowFrameExclusion.GROUP\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">GROUP</span></code></a>) 和并列项 (<a class=\"reference internal\" href=\"#django.db.models.expressions.WindowFrameExclusion.TIES\" title=\"django.db.models.expressions.WindowFrameExclusion.TIES\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">TIES</span></code></a>)：</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=\"o\">%</span><span class=\"p\">(</span><span class=\"n\">frame_type</span><span class=\"p\">)</span><span class=\"n\">s</span><span class=\"w\"> </span><span class=\"k\">BETWEEN</span><span class=\"w\"> </span><span class=\"o\">%</span><span class=\"p\">(</span><span class=\"k\">start</span><span class=\"p\">)</span><span class=\"n\">s</span><span class=\"w\"> </span><span class=\"k\">AND</span><span class=\"w\"> </span><span class=\"o\">%</span><span class=\"p\">(</span><span class=\"k\">end</span><span class=\"p\">)</span><span class=\"n\">s</span><span class=\"w\"> </span><span class=\"n\">EXCLUDE</span><span class=\"w\"> </span><span class=\"o\">%</span><span class=\"p\">(</span><span class=\"n\">exclusion</span><span class=\"p\">)</span><span class=\"n\">s</span>\n</code></pre></div>\n<p>帧缩小了用于计算结果的行。它们从某个起点移动到某个指定的终点。帧可以不分区使用，但通常情况下，指定窗口的排序以确保结果的确定性是个好主意。在帧中，帧中的对等值是指具有等值的行，如果不存在排序子句，则是指所有行。</p>\n<p>一个帧的默认起点是 <code class=\"docutils literal notranslate\"><span class=\"pre\">UNBOUNDED</span> <span class=\"pre\">PRECEDING</span></code>，即分区的第一行。终点总是显式地包含在 ORM 生成的 SQL 中，默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">UNBOUNDED</span> <span class=\"pre\">FOLLOWING</span></code>。默认帧包括从分区到集合中最后一行的所有行。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">start</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">end</span></code> 参数的可接受值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>、整数或零。<code class=\"docutils literal notranslate\"><span class=\"pre\">start</span></code> 的负整数结果为 <code class=\"docutils literal notranslate\"><span class=\"pre\">N</span> <span class=\"pre\">PRECEDING</span></code>，而 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> 产生 <code class=\"docutils literal notranslate\"><span class=\"pre\">UNBOUNDED</span> <span class=\"pre\">PRECEDING</span></code>。在 <code class=\"docutils literal notranslate\"><span class=\"pre\">ROWS</span></code> 模式下，<code class=\"docutils literal notranslate\"><span class=\"pre\">start</span></code> 可以使用正整数，结果为 <code class=\"docutils literal notranslate\"><span class=\"pre\">N</span> <span class=\"pre\">FOLLOWING</span></code>。<code class=\"docutils literal notranslate\"><span class=\"pre\">end</span></code> 可以接受正整数，结果为 <code class=\"docutils literal notranslate\"><span class=\"pre\">N</span> <span class=\"pre\">FOLLOWING</span></code>。在 <code class=\"docutils literal notranslate\"><span class=\"pre\">ROWS</span></code> 模式下，<code class=\"docutils literal notranslate\"><span class=\"pre\">end</span></code> 可以使用负整数，结果为 <code class=\"docutils literal notranslate\"><span class=\"pre\">N</span> <span class=\"pre\">PRECEDING</span></code>。对于 <code class=\"docutils literal notranslate\"><span class=\"pre\">start</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">end</span></code>，零将返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">CURRENT</span> <span class=\"pre\">ROW</span></code>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">CURRENT</span> <span class=\"pre\">ROW</span></code> 包括的内容有区别。当在 <code class=\"docutils literal notranslate\"><span class=\"pre\">ROWS</span></code> 模式下指定时，帧以当前行开始或结束。当在 <code class=\"docutils literal notranslate\"><span class=\"pre\">RANGE</span></code> 模式下指定时，根据排序子句，帧以第一个或最后一个对等值开始或结束。因此，<code class=\"docutils literal notranslate\"><span class=\"pre\">RANGE</span> <span class=\"pre\">CURRENT</span> <span class=\"pre\">ROW</span></code> 对具有由排序指定的相同值的行执行表达式。因为模板包括 <code class=\"docutils literal notranslate\"><span class=\"pre\">start</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">end</span></code> 点，所以可以用：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">ValueRange</span><span class=\"p\">(</span><span class=\"n\">start</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">,</span> <span class=\"n\">end</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>如果一部电影的“同行”被描述为由同一工作室在同一类型和同一年份发布的电影，那么这个 <code class=\"docutils literal notranslate\"><span class=\"pre\">RowRange</span></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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Avg</span><span class=\"p\">,</span> <span class=\"n\">F</span><span class=\"p\">,</span> <span class=\"n\">RowRange</span><span class=\"p\">,</span> <span class=\"n\">Window</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Movie</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">avg_rating</span><span class=\"o\">=</span><span class=\"n\">Window</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>        <span class=\"n\">expression</span><span class=\"o\">=</span><span class=\"n\">Avg</span><span class=\"p\">(</span><span class=\"s2\">&quot;rating&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>        <span class=\"n\">partition_by</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;studio&quot;</span><span class=\"p\">),</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;genre&quot;</span><span class=\"p\">)],</span>\n<span class=\"gp\">... </span>        <span class=\"n\">order_by</span><span class=\"o\">=</span><span class=\"s2\">&quot;released__year&quot;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>        <span class=\"n\">frame</span><span class=\"o\">=</span><span class=\"n\">RowRange</span><span class=\"p\">(</span><span class=\"n\">start</span><span class=\"o\">=-</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"n\">end</span><span class=\"o\">=</span><span class=\"mi\">2</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>    <span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n<p>如果数据库支持，您可以根据分区中表达式的值指定起始点和结束点。如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">Movie</span></code> 模型的 <code class=\"docutils literal notranslate\"><span class=\"pre\">released</span></code> 字段存储了每部电影的发布月份，那么这个 <code class=\"docutils literal notranslate\"><span class=\"pre\">ValueRange</span></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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Avg</span><span class=\"p\">,</span> <span class=\"n\">F</span><span class=\"p\">,</span> <span class=\"n\">ValueRange</span><span class=\"p\">,</span> <span class=\"n\">Window</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Movie</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">avg_rating</span><span class=\"o\">=</span><span class=\"n\">Window</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>        <span class=\"n\">expression</span><span class=\"o\">=</span><span class=\"n\">Avg</span><span class=\"p\">(</span><span class=\"s2\">&quot;rating&quot;</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>        <span class=\"n\">partition_by</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;studio&quot;</span><span class=\"p\">),</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;genre&quot;</span><span class=\"p\">)],</span>\n<span class=\"gp\">... </span>        <span class=\"n\">order_by</span><span class=\"o\">=</span><span class=\"s2\">&quot;released__year&quot;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>        <span class=\"n\">frame</span><span class=\"o\">=</span><span class=\"n\">ValueRange</span><span class=\"p\">(</span><span class=\"n\">start</span><span class=\"o\">=-</span><span class=\"mi\">12</span><span class=\"p\">,</span> <span class=\"n\">end</span><span class=\"o\">=</span><span class=\"mi\">12</span><span class=\"p\">),</span>\n<span class=\"gp\">... </span>    <span class=\"p\">),</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>为 <code class=\"docutils literal notranslate\"><span class=\"pre\">RowRange</span></code> 增加了对正整数 <code class=\"docutils literal notranslate\"><span class=\"pre\">start</span></code> 和负整数 <code class=\"docutils literal notranslate\"><span class=\"pre\">end</span></code> 的支持。</p>\n</aside>\n</section>\n</section>\n</section>\n<section id=\"technical-information\">\n<h2>技术信息<a class=\"heading-anchor\" href=\"#technical-information\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>下面你会发现对库作者可能有用的技术实现细节。下面的技术 API 和示例将有助于创建通用的查询表达式，可以扩展 Django 提供的内置功能。</p>\n<section id=\"expression-api\">\n<h3>表达式 API<a class=\"heading-anchor\" href=\"#expression-api\"><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/5.1/ref/models/lookups/#query-expression\"><span class=\"std std-ref\">查询表达式 API</span></a>，但也暴露了下面列出的一些额外的方法和属性。所有查询表达式必须继承于 <code class=\"docutils literal notranslate\"><span class=\"pre\">Expression()</span></code> 或相关子类。</p>\n<p>当一个查询表达式包装另一个表达式时，它负责在被包装的表达式上调用相应的方法。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Expression</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Expression\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.allowed_default\">\n<span class=\"sig-name descname\"><span class=\"pre\">allowed_default</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.allowed_default\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><aside class=\"version-note version-added\" data-version=\"5.0\">\n<p class=\"version-note-title\">New in Django 5.0</p></aside>\n<p>告诉 Django，这个表达式可以在 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/fields/#django.db.models.Field.db_default\" title=\"django.db.models.Field.db_default\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">Field.db_default</span></code></a> 中使用。默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.constraint_validation_compatible\">\n<span class=\"sig-name descname\"><span class=\"pre\">constraint_validation_compatible</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.constraint_validation_compatible\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><aside class=\"version-note version-added\" data-version=\"5.1\">\n<p class=\"version-note-title\">New in Django 5.1</p></aside>\n<p>告诉 Django 此表达式可以在约束验证期间使用。将 <code class=\"docutils literal notranslate\"><span class=\"pre\">constraint_validation_compatible</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> 的表达式必须只有一个源表达式。默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.contains_aggregate\">\n<span class=\"sig-name descname\"><span class=\"pre\">contains_aggregate</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.contains_aggregate\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>告诉 Django 这个表达式包含一个集合，需要在查询中添加一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">GROUP</span> <span class=\"pre\">BY</span></code> 子句。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.contains_over_clause\">\n<span class=\"sig-name descname\"><span class=\"pre\">contains_over_clause</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.contains_over_clause\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>告诉 Django 这个表达式包含一个 <a class=\"reference internal\" href=\"#django.db.models.expressions.Window\" title=\"django.db.models.expressions.Window\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Window</span></code></a> 表达式。例如，它用于在修改数据的查询中不允许使用窗口函数表达式。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.filterable\">\n<span class=\"sig-name descname\"><span class=\"pre\">filterable</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.filterable\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>告诉 Django 这个表达式可以在 <a class=\"reference internal\" href=\"/zh-hans/5.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\"><span class=\"pre\">QuerySet.filter()</span></code></a> 中引用。默认值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.window_compatible\">\n<span class=\"sig-name descname\"><span class=\"pre\">window_compatible</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.window_compatible\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>告诉 Django 这个表达式可以作为 <a class=\"reference internal\" href=\"#django.db.models.expressions.Window\" title=\"django.db.models.expressions.Window\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Window</span></code></a> 的源表达式。默认值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.empty_result_set_value\">\n<span class=\"sig-name descname\"><span class=\"pre\">empty_result_set_value</span></span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.empty_result_set_value\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>告诉 Django 在将表达式用于空结果集时应返回哪个值。默认值为 <a class=\"reference external\" href=\"https://docs.python.org/3/library/constants.html#NotImplemented\" title=\"(in Python v3.14)\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">NotImplemented</span></code></a>，它强制在数据库上计算表达式。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.resolve_expression\">\n<span class=\"sig-name descname\"><span class=\"pre\">resolve_expression</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">allow_joins</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">reuse</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">summarize</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">for_save</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.resolve_expression\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>提供在将表达式添加到查询之前进行任何预处理或验证的机会。还必须在任何嵌套表达式上调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">resolve_expression()</span></code>。应返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">self</span></code> 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">copy()</span></code>，并进行任何必要的转换。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">query</span></code> 是后端查询的实现。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">allow_joins</span></code> 是一个允许或拒绝在查询中使用连接的布尔值。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">reuse</span></code> 是一组可重用的多连接方案的连接。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">summarize</span></code> 是一个布尔值，当 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 时，表示正在计算的查询是一个终端聚合查询。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">for_save</span></code> 是一个布尔值，当 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 时，表示正在执行的查询正在进行创建或更新。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.get_source_expressions\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_source_expressions</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.get_source_expressions\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><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><span class=\"n\">Sum</span><span class=\"p\">(</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;foo&quot;</span><span class=\"p\">))</span><span class=\"o\">.</span><span class=\"n\">get_source_expressions</span><span class=\"p\">()</span>\n<span class=\"go\">[F(&#39;foo&#39;)]</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.set_source_expressions\">\n<span class=\"sig-name descname\"><span class=\"pre\">set_source_expressions</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expressions</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.set_source_expressions\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>获取一个表达式列表，并将其存储起来，使 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_source_expressions()</span></code> 能够返回它们。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.relabeled_clone\">\n<span class=\"sig-name descname\"><span class=\"pre\">relabeled_clone</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">change_map</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.relabeled_clone\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">self`</span></code> 的克隆（副本），并重新标明所有列别名。当创建子查询时，列别名会被重新命名。<code class=\"docutils literal notranslate\"><span class=\"pre\">relabeled_clone()</span></code> 也应该对任何嵌套的表达式进行调用并分配给克隆。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">change_map</span></code> 是一个将旧别名映射到新别名的字典。</p>\n<p>举例：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">relabeled_clone</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">change_map</span><span class=\"p\">):</span>\n    <span class=\"n\">clone</span> <span class=\"o\">=</span> <span class=\"n\">copy</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">)</span>\n    <span class=\"n\">clone</span><span class=\"o\">.</span><span class=\"n\">expression</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">expression</span><span class=\"o\">.</span><span class=\"n\">relabeled_clone</span><span class=\"p\">(</span><span class=\"n\">change_map</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">clone</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.convert_value\">\n<span class=\"sig-name descname\"><span class=\"pre\">convert_value</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">value</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expression</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">connection</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.convert_value\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个钩子，允许表达式将 <code class=\"docutils literal notranslate\"><span class=\"pre\">value`</span></code> 强制转换成一个更合适的类型。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">expression</span></code> 与 <code class=\"docutils literal notranslate\"><span class=\"pre\">self</span></code> 相同。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.get_group_by_cols\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_group_by_cols</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.get_group_by_cols\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>负责返回由此表达式引用的列的列表。应在任何嵌套表达式上调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_group_by_cols()</span></code>。特别是，<code class=\"docutils literal notranslate\"><span class=\"pre\">F()</span></code> 对象保存对列的引用。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.asc\">\n<span class=\"sig-name descname\"><span class=\"pre\">asc</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">nulls_first</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">nulls_last</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.asc\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回准备按升序排序的表达式。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">nulls_first</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">nulls_last</span></code> 定义了如何对空值进行排序。参见 <a class=\"reference internal\" href=\"#using-f-to-sort-null-values\"><span class=\"std std-ref\">使用 F() 对空值进行排序</span></a> 的用法示例。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.desc\">\n<span class=\"sig-name descname\"><span class=\"pre\">desc</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">nulls_first</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">nulls_last</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.desc\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回准备好降序排序的表达式。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">nulls_first</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">nulls_last</span></code> 定义了如何对空值进行排序。参见 <a class=\"reference internal\" href=\"#using-f-to-sort-null-values\"><span class=\"std std-ref\">使用 F() 对空值进行排序</span></a> 的用法示例。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.db.models.Expression.reverse_ordering\">\n<span class=\"sig-name descname\"><span class=\"pre\">reverse_ordering</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.db.models.Expression.reverse_ordering\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">self</span></code>，包括在 <code class=\"docutils literal notranslate\"><span class=\"pre\">order_by</span></code> 中对排序顺序进行的任何修改。例如，一个实现 <code class=\"docutils literal notranslate\"><span class=\"pre\">NULLS</span> <span class=\"pre\">LAST</span></code> 的表达式将把它的值改为 <code class=\"docutils literal notranslate\"><span class=\"pre\">NULLS</span> <span class=\"pre\">FIRST</span></code>。只有实现排序顺序的表达式，如 <code class=\"docutils literal notranslate\"><span class=\"pre\">OrderBy</span></code> 才需要修改。当 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.reverse\" title=\"django.db.models.query.QuerySet.reverse\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">reverse()</span></code></a> 在一个查询集上被调用时，会调用这个方法。</p>\n</dd></dl>\n\n</dd></dl>\n\n</section>\n<section id=\"writing-your-own-query-expressions\">\n<h3>编写自己的查询表达式<a class=\"heading-anchor\" href=\"#writing-your-own-query-expressions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你可以编写你自己的查询表达式类，这些类使用并可以与其他查询表达式集成。让我们通过一个例子，在不使用内置的 <a class=\"reference internal\" href=\"#func-expressions\"><span class=\"std std-ref\">Func() 表达式</span></a> 的情况下，编写一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">COALESCE</span></code> SQL 函数的实现。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">COALESCE</span></code> SQL 函数被定义为接收一个列或值的列表，它将返回第一个不是 <code class=\"docutils literal notranslate\"><span class=\"pre\">NULL</span></code> 的列或值。它将返回第一个不是 <code class=\"docutils literal notranslate\"><span class=\"pre\">NULL</span></code> 的列或值。</p>\n<p>我们将首先定义用于生成 SQL 的模板和一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> 方法来设置一些属性：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">copy</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Expression</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Coalesce</span><span class=\"p\">(</span><span class=\"n\">Expression</span><span class=\"p\">):</span>\n    <span class=\"n\">template</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;COALESCE( </span><span class=\"si\">%(expressions)s</span><span class=\"s2\"> )&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">expressions</span><span class=\"p\">,</span> <span class=\"n\">output_field</span><span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"n\">output_field</span><span class=\"o\">=</span><span class=\"n\">output_field</span><span class=\"p\">)</span>\n        <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">expressions</span><span class=\"p\">)</span> <span class=\"o\">&lt;</span> <span class=\"mi\">2</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"ne\">ValueError</span><span class=\"p\">(</span><span class=\"s2\">&quot;expressions must have at least 2 elements&quot;</span><span class=\"p\">)</span>\n        <span class=\"k\">for</span> <span class=\"n\">expression</span> <span class=\"ow\">in</span> <span class=\"n\">expressions</span><span class=\"p\">:</span>\n            <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"nb\">hasattr</span><span class=\"p\">(</span><span class=\"n\">expression</span><span class=\"p\">,</span> <span class=\"s2\">&quot;resolve_expression&quot;</span><span class=\"p\">):</span>\n                <span class=\"k\">raise</span> <span class=\"ne\">TypeError</span><span class=\"p\">(</span><span class=\"s2\">&quot;</span><span class=\"si\">%r</span><span class=\"s2\"> is not an Expression&quot;</span> <span class=\"o\">%</span> <span class=\"n\">expression</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">expressions</span> <span class=\"o\">=</span> <span class=\"n\">expressions</span>\n</code></pre></div>\n<p>我们对参数进行一些基本的验证，包括要求至少有 2 个列或值，并确保它们是表达式。我们在这里要求 <a class=\"reference internal\" href=\"#output-field\"><span class=\"std std-ref\">output_field</span></a>，以便 Django 知道应该将最终的结果分配给哪种模型字段。</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=\"w\"> </span><span class=\"nf\">resolve_expression</span><span class=\"p\">(</span>\n    <span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">query</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"n\">allow_joins</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span> <span class=\"n\">reuse</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"n\">summarize</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">,</span> <span class=\"n\">for_save</span><span class=\"o\">=</span><span class=\"kc\">False</span>\n<span class=\"p\">):</span>\n    <span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">copy</span><span class=\"p\">()</span>\n    <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">is_summary</span> <span class=\"o\">=</span> <span class=\"n\">summarize</span>\n    <span class=\"k\">for</span> <span class=\"n\">pos</span><span class=\"p\">,</span> <span class=\"n\">expression</span> <span class=\"ow\">in</span> <span class=\"nb\">enumerate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">expressions</span><span class=\"p\">):</span>\n        <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">expressions</span><span class=\"p\">[</span><span class=\"n\">pos</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">expression</span><span class=\"o\">.</span><span class=\"n\">resolve_expression</span><span class=\"p\">(</span>\n            <span class=\"n\">query</span><span class=\"p\">,</span> <span class=\"n\">allow_joins</span><span class=\"p\">,</span> <span class=\"n\">reuse</span><span class=\"p\">,</span> <span class=\"n\">summarize</span><span class=\"p\">,</span> <span class=\"n\">for_save</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">c</span>\n</code></pre></div>\n<p>接下来，我们编写负责生成 SQL 的方法：</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=\"w\"> </span><span class=\"nf\">as_sql</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">,</span> <span class=\"n\">template</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n    <span class=\"n\">sql_expressions</span><span class=\"p\">,</span> <span class=\"n\">sql_params</span> <span class=\"o\">=</span> <span class=\"p\">[],</span> <span class=\"p\">[]</span>\n    <span class=\"k\">for</span> <span class=\"n\">expression</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">expressions</span><span class=\"p\">:</span>\n        <span class=\"n\">sql</span><span class=\"p\">,</span> <span class=\"n\">params</span> <span class=\"o\">=</span> <span class=\"n\">compiler</span><span class=\"o\">.</span><span class=\"n\">compile</span><span class=\"p\">(</span><span class=\"n\">expression</span><span class=\"p\">)</span>\n        <span class=\"n\">sql_expressions</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">sql</span><span class=\"p\">)</span>\n        <span class=\"n\">sql_params</span><span class=\"o\">.</span><span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"n\">params</span><span class=\"p\">)</span>\n    <span class=\"n\">template</span> <span class=\"o\">=</span> <span class=\"n\">template</span> <span class=\"ow\">or</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">template</span>\n    <span class=\"n\">data</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s2\">&quot;expressions&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;,&quot;</span><span class=\"o\">.</span><span class=\"n\">join</span><span class=\"p\">(</span><span class=\"n\">sql_expressions</span><span class=\"p\">)}</span>\n    <span class=\"k\">return</span> <span class=\"n\">template</span> <span class=\"o\">%</span> <span class=\"n\">data</span><span class=\"p\">,</span> <span class=\"n\">sql_params</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">as_oracle</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    Example of vendor specific handling (Oracle in this case).</span>\n<span class=\"sd\">    Let&#39;s make the function name lowercase.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">as_sql</span><span class=\"p\">(</span><span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">,</span> <span class=\"n\">template</span><span class=\"o\">=</span><span class=\"s2\">&quot;coalesce( </span><span class=\"si\">%(expressions)s</span><span class=\"s2\"> )&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql()</span></code> 方法可以支持自定义关键字参数，允许 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_vendorname()</span></code> 方法覆盖用于生成 SQL 字符串的数据。使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql()</span></code> 关键字参数进行自定义最好是在 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_vendorname()</span></code> 方法中突变 <code class=\"docutils literal notranslate\"><span class=\"pre\">self</span></code>，因为后者在不同的数据库后端运行时可能会导致错误。如果你的类依赖于类属性来定义数据，可以考虑在你的 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql()</span></code> 方法中允许覆盖。</p>\n<p>我们使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">compiler.compile()</span></code> 方法为每个 <code class=\"docutils literal notranslate\"><span class=\"pre\">expressions</span></code> 生成 SQL，并将结果用逗号连接起来。然后在模板中填入我们的数据，并返回 SQL 和参数。</p>\n<p>我们还定义了一个专门针对 Oracle 后端的自定义实现。如果使用 Oracle 后端，将调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_oracle()</span></code> 函数，而不是 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql()</span></code>。</p>\n<p>最后，我们实现了其余的方法，使我们的查询表达式能够与其他查询表达式很好地配合：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_source_expressions</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><span class=\"n\">expressions</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">set_source_expressions</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">expressions</span><span class=\"p\">):</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">expressions</span> <span class=\"o\">=</span> <span class=\"n\">expressions</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><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">F</span><span class=\"p\">,</span> <span class=\"n\">Value</span><span class=\"p\">,</span> <span class=\"n\">CharField</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">qs</span> <span class=\"o\">=</span> <span class=\"n\">Company</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">annotate</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"n\">tagline</span><span class=\"o\">=</span><span class=\"n\">Coalesce</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>        <span class=\"p\">[</span><span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;motto&quot;</span><span class=\"p\">),</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;ticker_name&quot;</span><span class=\"p\">),</span> <span class=\"n\">F</span><span class=\"p\">(</span><span class=\"s2\">&quot;description&quot;</span><span class=\"p\">),</span> <span class=\"n\">Value</span><span class=\"p\">(</span><span class=\"s2\">&quot;No Tagline&quot;</span><span class=\"p\">)],</span>\n<span class=\"gp\">... </span>        <span class=\"n\">output_field</span><span class=\"o\">=</span><span class=\"n\">CharField</span><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><span class=\"k\">for</span> <span class=\"n\">c</span> <span class=\"ow\">in</span> <span class=\"n\">qs</span><span class=\"p\">:</span>\n<span class=\"gp\">... </span>    <span class=\"nb\">print</span><span class=\"p\">(</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=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">name</span><span class=\"p\">,</span> <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">tagline</span><span class=\"p\">))</span>\n<span class=\"gp\">...</span>\n<span class=\"go\">Google: Do No Evil</span>\n<span class=\"go\">Apple: AAPL</span>\n<span class=\"go\">Yahoo: Internet Company</span>\n<span class=\"go\">Django Software Foundation: No Tagline</span>\n</code></pre></div>\n<section id=\"avoiding-sql-injection\">\n<span id=\"avoiding-sql-injection-in-query-expressions\"></span><h4>避免 SQL 注入<a class=\"heading-anchor\" href=\"#avoiding-sql-injection\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>由于 <code class=\"docutils literal notranslate\"><span class=\"pre\">Func</span></code> 的关键字参数 <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> （<code class=\"docutils literal notranslate\"><span class=\"pre\">**extra</span></code>）和 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql()</span></code> （<code class=\"docutils literal notranslate\"><span class=\"pre\">**extra_context</span></code>）的参数是内插到 SQL 字符串中，而不是作为查询参数传递的（数据库驱动程序会对其进行转义处理），因此它们不能包含不受信任的用户输入。</p>\n<p>例如，如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">substring</span></code> 是用户提供的，这个函数就容易被 SQL 注入：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Func</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Position</span><span class=\"p\">(</span><span class=\"n\">Func</span><span class=\"p\">):</span>\n    <span class=\"n\">function</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;POSITION&quot;</span>\n    <span class=\"n\">template</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;</span><span class=\"si\">%(function)s</span><span class=\"s2\">(&#39;</span><span class=\"si\">%(substring)s</span><span class=\"s2\">&#39; in </span><span class=\"si\">%(expressions)s</span><span class=\"s2\">)&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">expression</span><span class=\"p\">,</span> <span class=\"n\">substring</span><span class=\"p\">):</span>\n        <span class=\"c1\"># substring=substring is an SQL injection vulnerability!</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"n\">expression</span><span class=\"p\">,</span> <span class=\"n\">substring</span><span class=\"o\">=</span><span class=\"n\">substring</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>这个函数在没有任何参数的情况下生成一个 SQL 字符串。由于 <code class=\"docutils literal notranslate\"><span class=\"pre\">substring</span></code> 是作为关键字参数传递给 <code class=\"docutils literal notranslate\"><span class=\"pre\">super().__init__()</span></code> 的，所以在将查询发送到数据库之前，它就被插入到 SQL 字符串中。</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\">class</span><span class=\"w\"> </span><span class=\"nc\">Position</span><span class=\"p\">(</span><span class=\"n\">Func</span><span class=\"p\">):</span>\n    <span class=\"n\">function</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;POSITION&quot;</span>\n    <span class=\"n\">arg_joiner</span> <span class=\"o\">=</span> <span class=\"s2\">&quot; IN &quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">expression</span><span class=\"p\">,</span> <span class=\"n\">substring</span><span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"n\">substring</span><span class=\"p\">,</span> <span class=\"n\">expression</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>用 <code class=\"docutils literal notranslate\"><span class=\"pre\">substring</span></code> 代替作为位置参数传递，它将作为数据库查询的参数传递。</p>\n</section>\n</section>\n<section id=\"adding-support-in-third-party-database-backends\">\n<h3>在第三方数据库后端增加支持<a class=\"heading-anchor\" href=\"#adding-support-in-third-party-database-backends\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你使用的数据库后端对某个函数使用了不同的 SQL 语法，你可以通过在函数的类上打一个新的方法来增加对它的支持。</p>\n<p>比方说，我们正在为微软的 SQL Server 编写一个后端，它使用 SQL 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">LEN</span></code> 而不是 <code class=\"docutils literal notranslate\"><span class=\"pre\">LENGTH</span></code> 来实现 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/models/database-functions/#django.db.models.functions.Length\" title=\"django.db.models.functions.Length\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Length</span></code></a> 函数。我们将把一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sqlserver()</span></code> 的新方法移植到 <code class=\"docutils literal notranslate\"><span class=\"pre\">Length</span></code> 类上：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models.functions</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Length</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">sqlserver_length</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">as_sql</span><span class=\"p\">(</span><span class=\"n\">compiler</span><span class=\"p\">,</span> <span class=\"n\">connection</span><span class=\"p\">,</span> <span class=\"n\">function</span><span class=\"o\">=</span><span class=\"s2\">&quot;LEN&quot;</span><span class=\"p\">)</span>\n\n\n<span class=\"n\">Length</span><span class=\"o\">.</span><span class=\"n\">as_sqlserver</span> <span class=\"o\">=</span> <span class=\"n\">sqlserver_length</span>\n</code></pre></div>\n<p>你也可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sql()</span></code> 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">template</span></code> 参数自定义 SQL。</p>\n<p>我们使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_sqlserver()</span></code>，因为 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.connection.vendor</span></code> 返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">sqlserver</span></code> 作为后端。</p>\n<p>第三方后端可以在后端包的顶层 <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__.py</span></code> 文件或从顶层 <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__.py</span></code> 导入的顶层 <code class=\"docutils literal notranslate\"><span class=\"pre\">expressions.py</span></code> 文件（或包）中注册它们的函数。</p>\n<p>对于希望给自己正在使用的后端打补丁的用户项目来说，这段代码应该存在于 <code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">AppConfig.ready()</span></code> 方法中。</p>\n</section>\n</section>","rootId":"query-expressions","toc":[{"title":"支持的算术","anchor":"supported-arithmetic","children":[]},{"title":"输出字段","anchor":"output-field","children":[]},{"title":"一些例子","anchor":"some-examples","children":[]},{"title":"内置表达式","anchor":"built-in-expressions","children":[{"title":"F() 表达式","anchor":"f-expressions","children":[{"title":"切片 F() 表达式","anchor":"slicing-f-expressions","children":[]},{"title":"使用 F() 避免竞争条件","anchor":"avoiding-race-conditions-using-f","children":[]},{"title":"F() 赋值在 Model.save() 之后持续存在","anchor":"f-assignments-persist-after-model-save","children":[]},{"title":"在过滤器中使用 F()","anchor":"using-f-in-filters","children":[]},{"title":"与注解一起使用 F()","anchor":"using-f-with-annotations","children":[]},{"title":"使用 F() 对空值进行排序","anchor":"using-f-to-sort-null-values","children":[]},{"title":"使用 F() 进行逻辑操作","anchor":"using-f-with-logical-operations","children":[]}]},{"title":"Func() 表达式","anchor":"func-expressions","children":[]},{"title":"Aggregate() 表达式","anchor":"aggregate-expressions","children":[]},{"title":"创建你自己的聚合函数","anchor":"creating-your-own-aggregate-functions","children":[]},{"title":"Value() 表达式","anchor":"value-expressions","children":[]},{"title":"ExpressionWrapper() 表达式","anchor":"expressionwrapper-expressions","children":[]},{"title":"条件表达式","anchor":"conditional-expressions","children":[]},{"title":"Subquery() 表达式","anchor":"subquery-expressions","children":[{"title":"从外部查询集中引用列","anchor":"referencing-columns-from-the-outer-queryset","children":[]},{"title":"将子查询限制为单列","anchor":"limiting-a-subquery-to-a-single-column","children":[]},{"title":"将子查询限制为单行","anchor":"limiting-the-subquery-to-a-single-row","children":[]},{"title":"Exists() 子查询","anchor":"exists-subqueries","children":[]},{"title":"对 Subquery() 或 Exists() 表达式进行过滤。","anchor":"filtering-on-a-subquery-or-exists-expressions","children":[]},{"title":"在 Subquery 表达式中使用集合。","anchor":"using-aggregates-within-a-subquery-expression","children":[]}]},{"title":"原始 SQL 表达式","anchor":"raw-sql-expressions","children":[]},{"title":"窗口函数","anchor":"window-functions","children":[{"title":"帧","anchor":"frames","children":[]}]}]},{"title":"技术信息","anchor":"technical-information","children":[{"title":"表达式 API","anchor":"expression-api","children":[]},{"title":"编写自己的查询表达式","anchor":"writing-your-own-query-expressions","children":[{"title":"避免 SQL 注入","anchor":"avoiding-sql-injection","children":[]}]},{"title":"在第三方数据库后端增加支持","anchor":"adding-support-in-third-party-database-backends","children":[]}]}],"breadcrumbs":[{"docname":"ref/index","title":"API 参考","url":"/zh-hans/5.1/ref/"},{"docname":"ref/models/index","title":"模型","url":"/zh-hans/5.1/ref/models/"}],"prev":{"docname":"ref/models/lookups","title":"查找 API 参考","url":"/zh-hans/5.1/ref/models/lookups/"},"next":{"docname":"ref/models/conditional-expressions","title":"条件表达式","url":"/zh-hans/5.1/ref/models/conditional-expressions/"},"formats":{"html":"/zh-hans/5.1/ref/models/expressions/","markdown":"/zh-hans/5.1/ref/models/expressions.md","json":"/zh-hans/5.1/ref/models/expressions.json"},"source":"https://github.com/django/django/blob/stable/5.1.x/docs/ref/models/expressions.txt","official":"https://docs.djangoproject.com/zh-hans/5.1/ref/models/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","it","pt-br","ko","es","el","pl"]}