系统检查框架是一套用于验证 Django 项目的静态检查。它检测常见的问题,并提供如何修复这些问题的提示。该框架是可扩展的,所以你可以很容易地添加自己的检查。
关于如何添加自己的检查并与 Django 的系统检查集成的细节,请看 系统检查主题指南。
CheckMessage¶CheckMessage(level, msg, hint=None, obj=None, id=None)¶系统检查提出的警告和错误必须是 CheckMessage 的实例。一个实例封装了一个单一的可报告的错误或警告。它还提供适用于该信息的上下文和提示,以及用于过滤目的的唯一标识符。
构造方法的参数:
levelDEBUG、INFO、WARNING、ERROR、CRITICAL。如果级别大于或等于 ERROR,那么 Django 将阻止管理命令的执行。等级小于 ``ERROR```的消息(即警告)会被报告到控制台,但可以被静默。msghintNone 值。objstr__() 方法的任何其他对象。该方法在报告所有消息时使用,其结果在消息之前。idapplabel.X001 的模式,其中 X 是字母 CEWID 中的一个,表示消息的严重性(C 表示严重,E 表示错误等)。这个数字可由应用程序分配,但在该应用程序内应是唯一的。有一些子类可以使创建具有通用级别的消息更容易。当使用它们时,你可以省略 level 参数,因为它已被类名所隐含。
Debug(msg, hint=None, obj=None, id=None)¶Info(msg, hint=None, obj=None, id=None)¶Warning(msg, hint=None obj=None, id=None)¶Error(msg, hint=None, obj=None, id=None)¶Critical(msg, hint=None, obj=None, id=None)¶Django 的系统检查按以下标签组织:
admin:检查所有管理站点的声明。async_support: 检查异步相关配置。caches:检查缓存相关的配置。compatibility:标记版本升级可能导致的问题。database:检查与数据库有关的配置问题。默认情况下不运行数据库检查,因为数据库检查的工作比普通检查的静态代码分析更多。只有通过 migrate 命令或在调用 check 命令时使用 --database 选项指定配置的数据库别名时,才会运行数据库检查。models:检查模型、字段和管理器定义。security:检查安全相关配置。signals:检查信号声明和处理器注册信息。sites : 检查 django.contrib.sites 配置。staticfiles:检查 django.contrib.staticfiles 配置。templates:检查模板相关配置。translation:检查翻译相关配置。urls:检查 URL 配置。一些可能通过多个标签同时注册的检查项。
增加了 async_support 标签。
database 检查现在只对使用 check --database 选项指定的数据库别名运行。
增加了 sites 标签。
以下检查验证了你对 异步支持 的配置:
DJANGO_ALLOW_ASYNC_UNSAFE 环境变量。这将禁用 异步安全保护。兼容性检查警告那些升级 Django 后可能出现的问题。
<pattern> 有一个 route 包含 (?P<、以 ^ 开始或以 $ 结束。这可能是在从 url() 迁移到 path() 时的一个疏忽。以下检查验证你的 CACHES 配置是否正确设置:
CACHES 配置中定义一个 'default' 缓存。<cache> 配置可能会暴露你的缓存或导致你的数据损坏,因为它的 LOCATION 匹配/是在/包含 MEDIA_ROOT / STATIC_ROOT / STATICFILES_DIRS。<cache> 缓存 LOCATION 是相对路径。请使用绝对路径。如果你使用的是 MySQL 或 MariaDB,将执行以下检查:
CharField 有一个 max_length > 255。这项检查在 Django 3.1 中 被改为 mysql.W003,因为真正的最大尺寸取决于许多因素。<alias> 未设置为严格模式。另见 设置 sql_mode。CharField 有 max_length > 255。"__"。pk 是保留关键字,不能作为字段名使用。choices 必须是可迭代对象(例如,列表或元组)。choices must be an iterable containing (actual value,
human readable name) tuples.db_index 必须是 None,True 或 False。null = True。validators 必须都是可调用的。max_length 太小,无法容纳 choices 中的最长值(<count> 字符)。<field> 默认值应该是一个可调用对象,而不是一个实例,这样就不会在所有字段实例之间共享。AutoField 必须设置 primary_key=True。BooleanField 不接受空值。这项检查出现在 Django 2.1 中增加对空值的支持之前。CharField 必须定义一个 max_length 属性。max_length 必须是个正整数。max_length 在使用 <integer field type> 时会被忽略。DecimalField 必须定义一个 decimal_places 属性。decimal_places 必须是个非负整数。DecimalField 必须定义一个 max_digits 属性。max_digits must be a positive integer.max_digits 必须大于或等于 decimal_places。FilePathField 的 allow_files 或 allow_folders 必须有一个被设为 True。GenericIPAddressFields cannot have blank=True if
null=False, as blank values are stored as nulls.auto_now、auto_now_add 和 default 等选项是相互排斥的。这些选项只能有一个。<database> 并不支持在 <field data type> 列上创建数据库索引。BinaryField 的 default 不能是字符串。使用字节内容代替。<database> 不支持 JSONField。<database> 不支持对 <field_type> 进行字符序设置。IPAddressField 已被删除,但历史迁移中的支持除外。IPAddressField 已被废弃。在 Django 1.9 中,将取消对它的支持(除了历史迁移)。这个检查出现在 Django 1.7 和 1.8 中。CommaSeparatedIntegerField 已被废弃。在 Django 2.0 中,对它的支持将被删除(除了在历史迁移中)。这个检查出现在 Django 1.10 和 1.11 中。CommaSeparatedIntegerField 已被删除,但历史迁移中的支持除外。FloatRangeField 已被废弃,将在 Django 3.1 中删除。这项检查出现在 Django 2.2 和 3.0 中。NullBooleanField 已被废弃。在 Django 4.0 中,将取消对它的支持(历史迁移除外)。django.contrib.postgres.fields.JSONField 已被废弃。对它的支持(除了在历史迁移中)将在 Django 4.0 中被删除。unique 不是 FileField 的有效参数。这项检查在 Django 1.11 中已被删除。primary_key 对于 FileField 来说不是个有效的参数。FileField 的 upload_to 参数必须是个相对路径,而不是一个相对路径。ImageField,因为未安装 Pillow。<swappable> 不是表单 app_label.app_name。<SETTING> 引用了 <model>,但该网站尚未安装,或者是抽象的。<app_label>.<model> 有两个相同的多对多关系。id 只有在字段也设置了 primary_key=True 的情况下才能用作字段名。<model> 中的字段 <field name> 与父模型 <model> 中的字段 <field name> 发生冲突。<field name> clashes with the field
<field name> from model <model>.<column name> 被其它字段使用的字段 <field name> 。index_together 必须是个列表或元组。index_together 元素都必须是列表或元组。unique_together 必须是个列表或元组。unique_together 元素都必须是列表或元组。constraints/indexes/index_together/unique_together 引用了不存在的字段 <field name>。constraints/indexes/index_together/unique_together 指向一个 ManyToManyField <field name>,但 ManyToManyField 不支持该选项。ordering 必须是个元组或列表(即便你只想按照一个字段进行排序)。ordering 指向是不存在的字段、相关字段或查找 <field name>。constraints/indexes/index_together/unique_together 指的是字段 <field_name>,该字段不在模型 <model> 的本地。<model>,包含模型字段。<field> 来说太长。数据库 <alias> 的最大长度为 <maximum length>。<M2M field> 来说太长。数据库 <alias> 的最大长度为 <maximum length>。<model>.check() 类方法目前被覆盖。ordering 和 order_with_respect_to 不能一起使用。<function> 包含对 <app label>.<model> 的惰性引用,但应用 <app label> 没有安装或没有提供模型 <model>。<model> 不能以下划线开头或结尾,因为它与查找语法相冲突。<model> 不能包含双下划线,因为它与查找语法相冲突。<property name> 属性与相关字段存取器发生冲突。primary_key=True 字段。<database> 不支持检查约束。db_table <db_table> 被多个模型使用:<model list>。<index> 对模型 <model> 不是唯一的。<index> 在模型 <model list> 中不是唯一的。<constraint> 对模型 <model> 不是唯一的。<constraint> 在模型 <model list> 中不是唯一的。<index> 不能以下划线或数字开头。<index> 不能长于 <max_length> 字符。db_table <db_table> 被多个模型使用:<model list>。<database> 不支持带有条件的唯一约束。<database> 不支持有条件的索引。<database> 不支持可推迟的唯一约束。<database> 不支持非键列的唯一约束。<database> 不支持带有非键列的索引。constraints 指向 join 字段 <field name>。django.db.models.AutoField。<database> 不支持对表达式的索引。安全检查并不能使你的网站安全。它们不会审计代码,进行入侵检测,或做任何特别复杂的事情。相反,它们有助于执行一个自动化的、唾手可得的检查清单,可以帮助你提高网站的安全性。
其中一些检查可能不适合你的特定部署配置。例如,如果你在负载均衡器中进行 HTTP 到 HTTPS 的重定向,那么不断地被警告没有启用 SECURE_SSL_REDIRECT 会很恼火。使用 SILENCED_SYSTEM_CHECKS 来关闭不需要的检查。
如果使用 check --deploy 选项,则会运行以下检查:
MIDDLEWARE 中没有 django.middleware.security.SecurityMiddleware,因此 SECURE_HSTS_SECONDS、SECURE_CONTENT_TYPE_NOSNIFF、SECURE_BROWSER_XSS_FILTER、SECURE_REFERRER_POLICY 和 SECURE_SSL_REDIRECT 配置将不起作用。MIDDLEWARE 中没有 django.middleware.clickjacking.XFrameOptionsMiddleware,因此你的页面不会使用 'x-frame-options' 头。除非有很好的理由让你的网站以框架形式提供服务,否则你应该考虑启用这个头以帮助防止点击劫持攻击。django.middleware.csrf.CsrfViewMiddleware 不在你的 MIDDLEWARE 中)。启用中间件是最安全的方法,以确保你不会留下任何漏洞。SECURE_HSTS_SECONDS 配置设置一个值。如果你的整个网站只通过 SSL 提供服务,你可能需要考虑设置一个值并启用 HTTP 严格传输安全。一定要先阅读文档,不小心启用 HSTS 会导致严重的、不可逆转的问题SECURE_HSTS_INCLUDE_SUBDOMAINS 设置为 True。如果没有这个设置,你的网站就有可能受到通过不安全连接到子域的攻击。只有当你确定你的域名的所有子域都应该只通过 SSL 来提供服务时,才将此设置为 True。SECURE_CONTENT_TYPE_NOSNIFF 配置没有设置为 True,因此你的网页不会以 'X-Content-Type-Options: nosniff' 头提供服务。你应该考虑启用这个头,以防止浏览器错误地识别内容类型。SECURE_BROWSER_XSS_FILTER `配置没有设置为 ``True`,所以你的页面将不会有 'X-XSS-Protection: 1; mode=block' 头。你应该考虑启用这个头来激活浏览器的 XSS 过滤,帮助防止 XSS 攻击。这个检查在 Django 3.0 中被删除了,因为 * ``X-XSS-Protection`` * 头不再被现代浏览器认可。SECURE_SSL_REDIRECT 配置没有设置为 True。除非你的网站需要通过 SSL 和非 SSL 连接,否则你可能需要将此设置设置为 True,或者配置一个负载平衡器或反向代理服务器,将所有连接重定向到 HTTPS。SECRET_KEY 少于 50 个字符,少于 5 个唯一字符,或者前缀为 'django-insecure-',表明它是由 Django 自动生成的。请生成一个长而随机的 SECRET_KEY,否则 Django 的许多安全关键功能将容易受到攻击。INSTALLED_APPS 中有 django.contrib.session,但你没有将 SESSION_COOKIE_SECURE 设置为 True。使用仅安全的会话 cookie 可以使网络流量嗅探器更难劫持用户会话。MIDDLEWARE 中有 django.contrib.session.middleware.SessionMiddleware,但你没有将 SESSION_COOKIE_SECURE 设置为 True。使用仅安全的会话 cookie 可以使网络流量嗅探器更难劫持用户会话SESSION_COOKIE_SECURE 未设置为 True。使用仅安全的会话 cookie 使网络流量嗅探者更难劫持用户会话。INSTALLED_APPS 中有 django.contrib.session,但你没有将 SESSION_COOKIE_HTTPONLY 设置为 True。使用 HttpOnly 的会话 cookie 可以使跨站脚本攻击更难劫持用户会话。MIDDLEWARE 中有 django.contrib.sessions.middleware.SessionMiddleware,但你没有将 SESSION_COOKIE_HTTPONLY 设置为 True。使用 HttpOnly 的会话 cookie 可以使跨站脚本攻击更难劫持用户会话。SESSION_COOKIE_HTTPONLY 未设置为 True。使用 HttpOnly 的会话 cookie 使跨站脚本攻击更难劫持用户会话。CSRF_COOKIE_SECURE 未设置为 True。使用仅安全的 CSRF cookie 会使网络流量嗅探者更难窃取 CSRF 令牌。CSRF_COOKIE_HTTPONLY 未设置为 True。使用 HttpOnly CSRF cookie 会使跨站脚本攻击更难窃取 CSRF 令牌。这个检查在 Django 1.11 中被删除了,因为 * :setting:`CSRF_COOKIE_HTTPONLY` * 配置没有实际的好处。DEBUG 设置为 True。MIDDLEWARE 中有 django.middleware.clickjacking.XFrameOptionsMiddleware,但 X_FRAME_OPTIONS 没有设置为 'DENY'。除非有很好的理由让你的网站在一个框架中为其他部分服务,否则你应该把它改为 'DENY'。ALLOWED_HOSTS 在部署时不得为空。SECURE_HSTS_PRELOAD 设置为 True。否则,你的网站将无法提交到浏览器预加载列表。SECURE_REFERRER_POLICY 配置。如果没有这个配置,你的网站将不会发送 Referrer-Policy 头。你应该考虑启用这个头以保护用户隐私。SECURE_REFERRER_POLICY 配置为无效值。以下检查验证你的安全相关配置是否正确设置:
DEFAULT_HASHING_ALGORITHM 必须是 'sha1' 或 'sha256'。'path.to.view' 没有使用正确的参数个数。'path.to.view'。<handler> 与 <signal> 信号连接,并惰性引用发送方 <app label>.<model>,但应用 <app label> 没有安装或没有提供模型 <model>。以下是对你的翻译配置进行的检查:
LANGUAGE_CODE 设置提供了一个无效值 setting: <value>。LANGUAGES 配置中提供了无效的语言代码 setting: <value>。LANGUAGES_BIDI 设置中提供了一个无效的语言代码 setting: <value>。LANGUAGE_CODE 配置提供了一个不在 LANGUAGES 配置中的值。以下检查项针对你的 URL 配置执行:
<pattern> 使用 include(),并以 $ 结尾的 route。把 route 中的美元符号去掉,以避免包含 URL 的问题。<pattern> 有一个以 / 开头的 route。请删除这个斜线,因为它是不必要的。如果这个模式是以 include() 为目标,请确保 include() 模式有一个尾部的 /。<pattern> 有一个 name,包括一个 :。去掉冒号,以避免模糊的命名空间引用。<pattern> 无效。确保 urlpatterns 是一个 path() 和/或 re_path() 实例的列表。<namespace> 不是唯一的。你可能无法反查此命名空间中的所有 URL。MEDIA_URL /STATIC_URL 的配置必须以斜线结束。handlerXXX 视图 ''path.to.view' 没有使用正确的参数数(...)。handlerXXX 视图 'path.to.view'。contrib 应用检查¶admin¶后台检查项均作为 admin 标签的一部分执行。
以下检查项在每个通过后台站点注册的 ModelAdmin (或其子类)上执行。
raw_id_fields 的值必须是个列表或元组。raw_id_fields[n] 的值指向 <field name>,它并不是 <model> 的属性。raw_id_fields[n] 的值必须是个外键或一个多对多字段。fields 的值必须是列表或元组。fieldsets 和 fields 都是定制的。fields 的值包含了重复字段。fieldsets 的值必须是个列表或元组。fieldsets[n] 的值必须是个列表或元组。fieldsets[n] 的值的长度必须是 2。fieldsets[n][1] 的值必须是个字典。fieldsets[n][1] 的值必须包含键 fields。fieldsets[n][1] 中有重复字段。fields[n]/fieldsets[n][m] 不能包括 ManyToManyField <field name>,因为该字段手动指定了一个关系模型。exclude 的值必须是个列表或元组。exclude 的值必须包含重复字段。form 的值必须继承自 BaseModelForm。filter_vertical 的值必须是个列表或元组。filter_horizontal 的值必须是个列表或元组。filter_vertical[n]/filter_horizontal[n] 的值指的是 <field name>,而这不是 <model> 的属性。filter_vertical[n]/filter_horizontal[n] 的值必须是多对多字段。radio_fields 的值必须是一个字典。radio_fields 的值指的是 <field name>,而这不是 <model> 的属性。radio_fields 的值指的是 <field name>,它不是 ForeignKey 的实例,也没有 choices 的定义。radio_fields[<field name>] 的值必须是 admin.HORIZONTAL 或 admin.VERTICAL。view_on_site 的值必须是可调用值或布尔值。prepopulated_fields 的值必须是一个字典。prepopulated_fields 的值指的是 <field name>,而这不是 <model> 的属性。prepopulated_fields 的值指的是 <field name>,它不得是 DateTimeField、ForeignKey、OneToOneField 或 ManyToManyField 字段。prepopulated_fields[<field name>] 的值必须是一个列表或元组。prepopulated_fields 的值指的是 <field name>,而这不是 <model> 的属性。ordering 的值必须是一个列表或元组。ordering 的值有随机排序标记 ?,但也有其他字段。ordering 的值指的是 <field name>,而该值不是 <model> 的属性。readonly_fields 的值必须是一个列表或元组。readonly_fields[n] 的值不是可调用对象,不是 <ModelAdmin class> 的属性,也不是 <model> 的属性。autocomplete_fields 的值必须是一个列表或元组。autocomplete_fields[n] 的值指的是 <field name>,而这不是 ``<model>``的属性。autocomplete_fields[n] 的值必须是外键或多对多字段。<model> 的管理必须注册,才能由 <modeladmin>.autocomplete_fields 引用。<modeladmin> 必须定义 search_fields,因为 <other_modeladmin>.autocomplete_fields 引用了它。ModelAdmin¶对管理站点注册的任何 ModelAdmin 进行以下检查:
save_as 的值必须是个布尔值。save_on_top 的值必须是个布尔值。inlines 的值必须是个列表或元组。<InlineModelAdmin class> 必须继承自 InlineModelAdmin。<InlineModelAdmin class> 必须有个 model 属性。<InlineModelAdmin class>.model 的值必须是个 Model。list_display 的值必须是个列表或元组。list_display[n] 的值指的是 <label>,而该值不是可调用对象,不是 <ModelAdmin class> 的属性,也不是 <model> 的属性或方法。list_display[n] 的值绝对不能是个 ManyToManyField 字段。list_display_links 的值必须是一个列表、一个元组或 None。list_display_links[n] 的值指的是 <label>,而 list_display 中没有定义。list_filter 的值必须是一个列表或元组。list_filter[n] 的值必须继承自 ListFilter。list_filter[n] 的值不得继承于 FieldListFilter。list_filter[n][1] 的值必须继承自 FieldListFilter。list_filter[n] 的值指的是 <label>,而该值并不指一个字段。list_select_related 的值必须是布尔值、元组或列表。list_per_page 的值必须是一个整数。list_max_show_all 的值必须是一个整数。list_editable 的值必须是一个列表或元组。list_editable[n] 的值指的是 <label>,而该值不是 <model> 的属性。list_editable[n] 的值指的是 <label>,而 list_display 中并不包含该值。list_editable[n] 的值不能同时出现在 list_editable 和 list_display_links 中。list_editable[n] 的值是指 list_display (<label>)中的第一个字段,除非设置 list_display_links,否则不能使用。list_editable[n] 的值指的是 <field name>,不能通过管理编辑。search_fields 的值必须是一个列表或元组。date_hierarchy 的值指的是 <field name>,而该值并不指的是一个字段。date_hierarchy 的值必须是 DateField 或 DateTimeField。<modeladmin> 必须为 <action> 动作定义一个 has_<foo>_permission() 方法。<modeladmin> 中定义的行动的 __name__ 属性必须是唯一的。<name> 这个名称不是唯一的。InlineModelAdmin¶对任何 InlineModelAdmin 上注册为内联的 ModelAdmin 进行以下检查。
<field name>,因为它是父模型 <app_label>.<model> 的外键。<model> 没有 ForeignKey 到 <parent model>./ <model> 有一个以上 ForeignKey 到 <parent model>。你必须指定一个 fk_name 属性。extra 的值必须是一个整数。max_num 的值必须是一个整数。min_num 的值必须是一个整数。formset 的值必须继承自 BaseModelFormSet。GenericInlineModelAdmin¶以下检查将在任何 GenericInlineModelAdmin 上作为内联注册的 ModelAdmin 上执行。
'ct_field' 引用了 <label>,这不是 <model> 上的一个字段。'ct_fk_field' 引用了 <label>,这不是 <model> 上的一个字段。<model> 没有 GenericForeignKey。<model> 没有 GenericForeignKey,使用内容类型字段 <field name> 和对象 ID 字段 <field name>。AdminSite¶对默认的 AdminSite 进行以下检查:
django.contrib.contenttypes 必须在 INSTALLED_APPS 中才能使用管理应用程序。DjangoTemplates (TEMPLATES)中启用 django.contrib.auth.context_processors.auth,才能使用管理程序。TEMPLATES 中配置一个 django.template.backends.django.DjangoTemplates 实例,才能使用管理程序。django.contrib.message.context_processors.message 必须在 DjangoTemplates (TEMPLATES)中启用,才能使用管理程序。django.contrib.auth 必须在 INSTALLED_APPS 中才能使用管理程序。django.contrib.messages 必须在 INSTALLED_APPS 中才能使用管理程序。django.contrib.auth.middleware.AuthenticationMiddleware 必须在 MIDDLEWARE 中才能使用管理应用程序。django.contrib.messages.middleware.MessageMiddleware 必须在 MIDDLEWARE 中才能使用管理应用程序。django.contrib.session.middleware.SessionMiddleware 必须在 MIDDLEWARE 中才能使用管理应用程序。DjangoTemplates (TEMPLATES)中启用 django.template.context_processors.request 才能使用管理员导航侧栏。auth¶REQUIRED_FIELDS 必须是一个列表或元组。REQUIRED_FIELDS 中不得包括名为 USERNAME_FIELD 的自定义用户模型字段。<field> 必须是唯一的,因为它被命名为 USERNAME_FIELD。<field> 被命名为 USERNAME_FIELD,但它不是唯一的。<codename> 的权限与模型 <model> 的内置权限发生冲突。<codename> 的权限与模型 <model> 重复。<model> 的 verbose_name 必须最多 244 个字符,其内置的权限名最多只能是 255 个字符。<model> 的权限名 <name> 超过 255 个字符。<User model>.is_anonymous 必须是一个属性或属性,而不是方法。忽略这一点是一个安全问题,因为匿名用户将被视为经过认证的用户。<User model>.is_authenticated 必须是一个属性或属性,而不是方法。忽略这一点是一个安全问题,因为匿名用户将被视为经过认证的用户。<model> 的名称最多只能是 93 个字符,其内置的权限名称最多只能是 100 个字符。<codename> 的模型 <model> 的权限超过100个字符。contenttypes¶当一个模型包含 GenericForeignKey 或 GenericRelation 时,会进行以下检查:
GenericForeignKey 对象 ID 引用不存在的字段 <field>。GenericForeignKey 内容类型引用不存在的字段 <field>。<field> 不是一个 ForeignKey。<field> 不是一个指向 contenttypes.ContentType 的 ForeignKey 。postgres¶对 django.contrib.postgres 模型字段进行以下检查:
<field> 缺省值应该是一个可调用对象,而不是一个实例,这样它就不会被所有字段实例共享。这个检查在 Django 3.1 中被改为 *``fields.E010`` *。sites¶对任何使用 CurrentSiteManager 的模型进行以下检查:
CurrentSiteManager 找不到名为 <field name> 的字段。CurrentSiteManager 不能使用 <field>,因为它不是外键或多对多字段。以下检查验证 django.contrib.sites 是否正确配置:
SITE_ID 的配置必须是一个整数。staticfiles¶以下检查验证 django.contrib.staticfiles 是否正确配置:
STATICFILES_DIRS 配置不是元组或列表。STATICFILES_DIRS 配置不应包含 STATIC_ROOT 配置。STATICFILES_DIRS 设置中的前缀 <prefix>,不得以斜线结束。12月 07, 2021