{"title":"系统检查框架","version":"6.0","locale":"zh-hans","docname":"topics/checks","url":"/zh-hans/6.0/topics/checks/","canonical":"https://djangodocs.dev/zh-hans/6.0/topics/checks/","summary":"系统检查框架是一组验证Django项目的静态检查。 它检测到常见的问题，并提供了如何解决这些问题的提示。 该框架是可扩展的，所以你可以轻松地添加自己的检查。 通过 check 命令来显示的触发检查操作。检查会在大多数命令之前被隐式触发，包括 runserver 和 migrate 。出于性能原因，检查不会作为部署中使用的…","html":"<span id=\"system-check-framework\"></span><h1>系统检查框架<a class=\"heading-anchor\" href=\"#module-django.core.checks\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>系统检查框架是一组验证Django项目的静态检查。 它检测到常见的问题，并提供了如何解决这些问题的提示。 该框架是可扩展的，所以你可以轻松地添加自己的检查。</p>\n<p>通过 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-check\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">check</span></code></a> 命令来显示的触发检查操作。检查会在大多数命令之前被隐式触发，包括 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-runserver\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">runserver</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> 。出于性能原因，检查不会作为部署中使用的 WSGI 堆栈的一部分来运行。如果你需要在部署系统上运行系统检查，可以使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-check\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">check</span></code></a> 来触发他们。</p>\n<p>严重的错误将阻止 Django 命令（比如 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-runserver\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">runserver</span></code></a>）运行。小问题将会在控制台上报告出来。如果你已经检查了警告的原因并愿意忽略它，你可以在 settings.py 文件里的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SILENCED_SYSTEM_CHECKS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SILENCED_SYSTEM_CHECKS</span></code></a> 设置隐藏指定的警告。</p>\n<p>Django 引发的所有检查的完整列表在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/checks/\"><span class=\"doc\">System check reference</span></a> 中可查。</p>\n<section id=\"writing-your-own-checks\">\n<h2>编写自定义的检查<a class=\"heading-anchor\" href=\"#writing-your-own-checks\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>框架是可伸缩的，并且允许你编写函数来执行其他你需要的其他检查。举例：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.checks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Error</span><span class=\"p\">,</span> <span class=\"n\">register</span>\n\n\n<span class=\"nd\">@register</span><span class=\"p\">()</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">example_check</span><span class=\"p\">(</span><span class=\"n\">app_configs</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"n\">errors</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n    <span class=\"c1\"># ... your check logic here</span>\n    <span class=\"k\">if</span> <span class=\"n\">check_failed</span><span class=\"p\">:</span>\n        <span class=\"n\">errors</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span>\n            <span class=\"n\">Error</span><span class=\"p\">(</span>\n                <span class=\"s2\">&quot;an error&quot;</span><span class=\"p\">,</span>\n                <span class=\"n\">hint</span><span class=\"o\">=</span><span class=\"s2\">&quot;A hint.&quot;</span><span class=\"p\">,</span>\n                <span class=\"n\">obj</span><span class=\"o\">=</span><span class=\"n\">checked_object</span><span class=\"p\">,</span>\n                <span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"s2\">&quot;myapp.E001&quot;</span><span class=\"p\">,</span>\n            <span class=\"p\">)</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">errors</span>\n</code></pre></div>\n<p>check 函数必须接受一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">app_configs</span></code> 参数；这个参数是应该被检查的应用程序的列表。如果为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>，则必须在项目中的 <em>所有</em> 已安装的应用程序上运行检查。</p>\n<p>检查将接收一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">databases</span></code> 关键字参数。这是一个数据库别名的列表，其连接可能用于检查数据库级别的配置。如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">databases</span></code> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>，则检查必须不使用任何数据库连接。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">**kwargs</span></code> 参数是为了将来扩展而必需的。</p>\n<section id=\"messages\">\n<h3>消息<a class=\"heading-anchor\" href=\"#messages\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>函数必须返回消息列表。如果检查结果没有发现问题，检查函数必须返回空列表。</p>\n<p>警告和错误由必须是 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/checks/#django.core.checks.CheckMessage\" title=\"django.core.checks.CheckMessage\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CheckMessage</span></code></a> 的检查方法引发。<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/checks/#django.core.checks.CheckMessage\" title=\"django.core.checks.CheckMessage\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CheckMessage</span></code></a> 的实例概括了错误或警告。它也提供适合消息的上下文和消息，和用来过滤目的的唯一标示。</p>\n<p>这个概念与来自  <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/contrib/messages/\"><span class=\"doc\">message framework</span></a> or the <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/logging/\"><span class=\"doc\">logging framework</span></a> 的消息非常相似。消息标有 <code class=\"docutils literal notranslate\"><span class=\"pre\">level</span></code> ，标示消息的严重性。</p>\n<p>也可以有快捷方式来简单创建公共级别的消息。当使用这些类你可以忽略 <code class=\"docutils literal notranslate\"><span class=\"pre\">level</span></code> 参数，因为它已经通过类名隐含。</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/checks/#django.core.checks.Debug\" title=\"django.core.checks.Debug\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Debug</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/checks/#django.core.checks.Info\" title=\"django.core.checks.Info\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Info</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/checks/#django.core.checks.Warning\" title=\"django.core.checks.Warning\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Warning</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/checks/#django.core.checks.Error\" title=\"django.core.checks.Error\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Error</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/checks/#django.core.checks.Critical\" title=\"django.core.checks.Critical\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Critical</span></code></a></p></li>\n</ul>\n</section>\n<section id=\"registering-and-labeling-checks\">\n<span id=\"registering-labeling-checks\"></span><h3>注册和标记检查<a class=\"heading-anchor\" href=\"#registering-and-labeling-checks\"><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/6.0/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">AppConfig.ready()</span></code></a> 方法中。</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.core.checks.register\">\n<span class=\"sig-name descname\"><span class=\"pre\">register</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">*tags)(function</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.core.checks.register\"><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\">register</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.core.checks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">register</span><span class=\"p\">,</span> <span class=\"n\">Tags</span>\n\n\n<span class=\"nd\">@register</span><span class=\"p\">(</span><span class=\"n\">Tags</span><span class=\"o\">.</span><span class=\"n\">compatibility</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_check</span><span class=\"p\">(</span><span class=\"n\">app_configs</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ... perform compatibility checks and collect errors</span>\n    <span class=\"k\">return</span> <span class=\"n\">errors</span>\n</code></pre></div>\n<p>你可以注册仅与生产配置文件相关的&quot;部署检查&quot; ：</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=\"nd\">@register</span><span class=\"p\">(</span><span class=\"n\">Tags</span><span class=\"o\">.</span><span class=\"n\">security</span><span class=\"p\">,</span> <span class=\"n\">deploy</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_check</span><span class=\"p\">(</span><span class=\"n\">app_configs</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>这些检查只在使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#cmdoption-check-deploy\"><code class=\"xref std std-option docutils literal notranslate\"><span class=\"pre\">check</span> <span class=\"pre\">--deploy</span></code></a> 选项时运行。</p>\n<p>你也可以把 <code class=\"docutils literal notranslate\"><span class=\"pre\">register</span></code> 当做函数而不是装饰器，通过传递一个可调用对象（通常是函数）作为第一参数传递给 <code class=\"docutils literal notranslate\"><span class=\"pre\">register</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\">my_check</span><span class=\"p\">(</span><span class=\"n\">app_configs</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n\n\n<span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">my_check</span><span class=\"p\">,</span> <span class=\"n\">Tags</span><span class=\"o\">.</span><span class=\"n\">security</span><span class=\"p\">,</span> <span class=\"n\">deploy</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"field-constraint-model-manager-template-engine-task-and-database-checks\">\n<span id=\"field-checking\"></span><h3>Field, constraint, model, manager, template engine, task, and database checks<a class=\"heading-anchor\" href=\"#field-constraint-model-manager-template-engine-task-and-database-checks\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>在某些情况下，你不需要注册检查函数——你可以使用现有的注册。</p>\n<p>Fields, constraints, models, model managers, template engines, task backends,\nand database backends all implement a <code class=\"docutils literal notranslate\"><span class=\"pre\">check()</span></code> method that is already\nregistered with the check framework. If you want to add extra checks, you can\nextend the implementation on the base class, perform any extra checks you need,\nand append any messages to those generated by the base class. It's recommended\nthat you delegate each check to separate methods.</p>\n<p>考虑一个例子，你正在实现一个自定义字段 <code class=\"docutils literal notranslate\"><span class=\"pre\">RangedIntegerField</span></code>。这个字段添加 <code class=\"docutils literal notranslate\"><span class=\"pre\">min</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">max</span></code> 参数给 <code class=\"docutils literal notranslate\"><span class=\"pre\">IntegerField</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.core</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">checks</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">RangedIntegerField</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">IntegerField</span><span class=\"p\">):</span>\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=\"nb\">min</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"nb\">max</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</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=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min</span> <span class=\"o\">=</span> <span class=\"nb\">min</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">max</span> <span class=\"o\">=</span> <span class=\"nb\">max</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">check</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Call the superclass</span>\n        <span class=\"n\">errors</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">check</span><span class=\"p\">(</span><span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n        <span class=\"c1\"># Do some custom checks and add messages to `errors`:</span>\n        <span class=\"n\">errors</span><span class=\"o\">.</span><span class=\"n\">extend</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">_check_min_max_values</span><span class=\"p\">(</span><span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">))</span>\n\n        <span class=\"c1\"># Return all errors and warnings</span>\n        <span class=\"k\">return</span> <span class=\"n\">errors</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">_check_min_max_values</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span> <span class=\"ow\">and</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">max</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span> <span class=\"ow\">and</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min</span> <span class=\"o\">&gt;</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">max</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"p\">[</span>\n                <span class=\"n\">checks</span><span class=\"o\">.</span><span class=\"n\">Error</span><span class=\"p\">(</span>\n                    <span class=\"s2\">&quot;min greater than max.&quot;</span><span class=\"p\">,</span>\n                    <span class=\"n\">hint</span><span class=\"o\">=</span><span class=\"s2\">&quot;Decrease min or increase max.&quot;</span><span class=\"p\">,</span>\n                    <span class=\"n\">obj</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"p\">,</span>\n                    <span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"s2\">&quot;myapp.E001&quot;</span><span class=\"p\">,</span>\n                <span class=\"p\">)</span>\n            <span class=\"p\">]</span>\n        <span class=\"c1\"># When no error, return an empty list</span>\n        <span class=\"k\">return</span> <span class=\"p\">[]</span>\n</code></pre></div>\n<p>如果你想对模型管理器添加检查，你应该对 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/db/managers/#django.db.models.Manager\" title=\"django.db.models.Manager\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Manager</span></code></a> 的子类采用相同方法。</p>\n<p>如果你想对模型类添加检查，这个方法几乎相同，唯一的区别是这个检查是一个类方法，而不是实例方法。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyModel</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"nd\">@classmethod</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">check</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">errors</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">check</span><span class=\"p\">(</span><span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n        <span class=\"c1\"># ... your own checks ...</span>\n        <span class=\"k\">return</span> <span class=\"n\">errors</span>\n</code></pre></div>\n<aside class=\"version-note version-changed\" data-version=\"6.0\">\n<p class=\"version-note-title\">Changed in Django 6.0</p><p>In older versions, constraints didn't implement a <code class=\"docutils literal notranslate\"><span class=\"pre\">check()</span></code> method.</p>\n</aside>\n</section>\n<section id=\"writing-tests\">\n<h3>编写测试<a class=\"heading-anchor\" href=\"#writing-tests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>消息具有可比性。允许你轻松编写测试：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.checks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Error</span>\n\n<span class=\"n\">errors</span> <span class=\"o\">=</span> <span class=\"n\">checked_object</span><span class=\"o\">.</span><span class=\"n\">check</span><span class=\"p\">()</span>\n<span class=\"n\">expected_errors</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"n\">Error</span><span class=\"p\">(</span>\n        <span class=\"s2\">&quot;an error&quot;</span><span class=\"p\">,</span>\n        <span class=\"n\">hint</span><span class=\"o\">=</span><span class=\"s2\">&quot;A hint.&quot;</span><span class=\"p\">,</span>\n        <span class=\"n\">obj</span><span class=\"o\">=</span><span class=\"n\">checked_object</span><span class=\"p\">,</span>\n        <span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"s2\">&quot;myapp.E001&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n<span class=\"p\">]</span>\n<span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">errors</span><span class=\"p\">,</span> <span class=\"n\">expected_errors</span><span class=\"p\">)</span>\n</code></pre></div>\n<section id=\"writing-integration-tests\">\n<h4>编写集成测试<a class=\"heading-anchor\" href=\"#writing-integration-tests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>由于在应用程序加载时需要注册某些检查，因此测试它们在系统检查框架内的集成可以是有用的。这可以通过使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django.core.management.call_command\" title=\"django.core.management.call_command\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">call_command()</span></code></a> 函数来实现。</p>\n<p>例如，这个测试演示了:setting:SITE_ID 设置必须是一个整数，这是来自站点框架的内置 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/checks/#sites-system-checks\"><span class=\"std std-ref\">检查</span></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.core.management</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">call_command</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.management.base</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SystemCheckError</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SimpleTestCase</span><span class=\"p\">,</span> <span class=\"n\">modify_settings</span><span class=\"p\">,</span> <span class=\"n\">override_settings</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SystemCheckIntegrationTest</span><span class=\"p\">(</span><span class=\"n\">SimpleTestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@override_settings</span><span class=\"p\">(</span><span class=\"n\">SITE_ID</span><span class=\"o\">=</span><span class=\"s2\">&quot;non_integer&quot;</span><span class=\"p\">)</span>\n    <span class=\"nd\">@modify_settings</span><span class=\"p\">(</span><span class=\"n\">INSTALLED_APPS</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;prepend&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.contrib.sites&quot;</span><span class=\"p\">})</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_non_integer_site_id</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">message</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;(sites.E101) The SITE_ID setting must be an integer.&quot;</span>\n        <span class=\"k\">with</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertRaisesMessage</span><span class=\"p\">(</span><span class=\"n\">SystemCheckError</span><span class=\"p\">,</span> <span class=\"n\">message</span><span class=\"p\">):</span>\n            <span class=\"n\">call_command</span><span class=\"p\">(</span><span class=\"s2\">&quot;check&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>考虑以下检查，如果自定义设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">ENABLE_ANALYTICS</span></code> 未设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</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.conf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">settings</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.checks</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"ne\">Warning</span><span class=\"p\">,</span> <span class=\"n\">register</span>\n\n\n<span class=\"nd\">@register</span><span class=\"p\">(</span><span class=\"s2\">&quot;myapp&quot;</span><span class=\"p\">,</span> <span class=\"n\">deploy</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">check_enable_analytics_is_true_on_deploy</span><span class=\"p\">(</span><span class=\"n\">app_configs</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"n\">errors</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n    <span class=\"k\">if</span> <span class=\"nb\">getattr</span><span class=\"p\">(</span><span class=\"n\">settings</span><span class=\"p\">,</span> <span class=\"s2\">&quot;ENABLE_ANALYTICS&quot;</span><span class=\"p\">,</span> <span class=\"kc\">None</span><span class=\"p\">)</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">True</span><span class=\"p\">:</span>\n        <span class=\"n\">errors</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span>\n            <span class=\"ne\">Warning</span><span class=\"p\">(</span>\n                <span class=\"s2\">&quot;The ENABLE_ANALYTICS setting should be set to True in deployment.&quot;</span><span class=\"p\">,</span>\n                <span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"s2\">&quot;myapp.W001&quot;</span><span class=\"p\">,</span>\n            <span class=\"p\">)</span>\n        <span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">errors</span>\n</code></pre></div>\n<p>鉴于这个检查不会引发 <code class=\"docutils literal notranslate\"><span class=\"pre\">SystemCheckError</span></code>，可以通过以下方式断言 <code class=\"docutils literal notranslate\"><span class=\"pre\">stderr</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\">io</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">StringIO</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.management</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">call_command</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SimpleTestCase</span><span class=\"p\">,</span> <span class=\"n\">override_settings</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">EnableAnalyticsDeploymentCheckTest</span><span class=\"p\">(</span><span class=\"n\">SimpleTestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@override_settings</span><span class=\"p\">(</span><span class=\"n\">ENABLE_ANALYTICS</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_when_set_to_none</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">stderr</span> <span class=\"o\">=</span> <span class=\"n\">StringIO</span><span class=\"p\">()</span>\n        <span class=\"n\">call_command</span><span class=\"p\">(</span><span class=\"s2\">&quot;check&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;-t&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;myapp&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;--deploy&quot;</span><span class=\"p\">,</span> <span class=\"n\">stderr</span><span class=\"o\">=</span><span class=\"n\">stderr</span><span class=\"p\">)</span>\n        <span class=\"n\">message</span> <span class=\"o\">=</span> <span class=\"p\">(</span>\n            <span class=\"s2\">&quot;(myapp.W001) The ENABLE_ANALYTICS setting should be set &quot;</span>\n            <span class=\"s2\">&quot;to True in deployment.&quot;</span>\n        <span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertIn</span><span class=\"p\">(</span><span class=\"n\">message</span><span class=\"p\">,</span> <span class=\"n\">stderr</span><span class=\"o\">.</span><span class=\"n\">getvalue</span><span class=\"p\">())</span>\n</code></pre></div>\n</section>\n</section>\n</section>","rootId":"module-django.core.checks","toc":[{"title":"编写自定义的检查","anchor":"writing-your-own-checks","children":[{"title":"消息","anchor":"messages","children":[]},{"title":"注册和标记检查","anchor":"registering-and-labeling-checks","children":[]},{"title":"Field, constraint, model, manager, template engine, task, and database checks","anchor":"field-constraint-model-manager-template-engine-task-and-database-checks","children":[]},{"title":"编写测试","anchor":"writing-tests","children":[{"title":"编写集成测试","anchor":"writing-integration-tests","children":[]}]}]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/6.0/topics/"}],"prev":{"docname":"topics/signals","title":"信号","url":"/zh-hans/6.0/topics/signals/"},"next":{"docname":"topics/external-packages","title":"扩展包","url":"/zh-hans/6.0/topics/external-packages/"},"formats":{"html":"/zh-hans/6.0/topics/checks/","markdown":"/zh-hans/6.0/topics/checks.md","json":"/zh-hans/6.0/topics/checks.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/topics/checks.txt","official":"https://docs.djangoproject.com/zh-hans/6.0/topics/checks/","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","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}