本文档涵盖了 django.utils
中所有稳定的模块。django.utils
中的大部分模块都是为内部使用而设计的,只有以下部分可以被认为是稳定的,因此根据 内部发布废弃政策 的规定,这些模块可以向后兼容。
django.utils.cache
¶这个模块包含了控制 HTTP 缓存的辅助函数。它通过管理响应的 Vary
头来实现。它包括直接对响应对象的头进行修补的函数,以及改变函数使其自己进行头修补的装饰器。
有关 Vary
标头的信息,请参阅 RFC 9110 Section 12.5.5。
本质上,Vary
HTTP 头定义了缓存在建立缓存密钥时应该考虑哪些头信息。如果请求的路径相同,但 Vary
中命名的头内容不同,则需要获得不同的缓存密钥,以防止传递错误的内容。
例如, 国际化 中间件需要通过 Accept-language
头来区分缓存。
这个函数通过添加所有关键字参数来修补 Cache-Control
头。变化如下:
所有的关键字参数名都转为小写,下划线转为连字符。
如果一个参数的值是 True
(确切地说是 True
,而不仅仅是一个真值),那么只有参数名称会被添加到头。
所有其他参数在应用 str()
后,都会加上其值。
为给定的 HttpResponse
对象添加一些有用的头信息。
Expires
Cache-Control
每个头只有在还没有设置的情况下才会被添加。
cache_timeout
的单位是秒。默认使用 CACHE_MIDDLEWARE_SECONDS
配置。
在当前日期/时间上添加一个 Expires
标头。
在响应中添加 Cache-Control: max-age=0, no-cache, no-store, must-revalidate, private
头,以表明页面永远不会被缓存。
每个头只有在还没有设置的情况下才会被添加。
在给定的 HttpResponse
对象中添加(或更新) Vary
标头。newheaders
是一个应该包含在 Vary
中的标头名称列表。如果标头包含一个星号,那么根据 RFC 9110 Section 12.5.5,Vary
标头将由一个单独的星号 '*'
组成。否则,不会删除 Vary
中的现有标头。
django.utils.dateparse
¶本模块中定义的函数共享以下属性:
它们接受 ISO 8601 日期/时间格式的字符串(或一些接近的替代格式),并从 Python 的 datetime
模块的相应类中返回对象。
如果他们的输入格式很好,但不是有效的日期或时间,他们会引发 ValueError
。
如果输入格式不好,则返回 None
。
它们接受最多皮秒精度的输入,但它们将其截断为微秒,因为这是 Python 支持的。
解析一个字符串并返回一个 datetime.date
。
解析一个字符串并返回一个 datetime.time
。
不支持 UTC 偏移;如果 value
描述的是 UTC 偏移,结果是 None
。
解析一个字符串并返回一个 datetime.datetime
。
支持 UTC 偏移;如果 value
描述的是 UTC 偏移,则结果的 tzinfo
属性是一个 datetime.timezone
实例。
解析一个字符串并返回一个 datetime.timedelta
。
要求数据格式为 "DD HH:MM:SS.uuuuu"
、"DD HH:MM:SS,uuuuu"
或 ISO 8601 规定的格式(例如 P4DT1H15M20S
相当于 4 1:15:20
)或 PostgreSQL 的日期时间间隔格式(例如 3 days 04:05:06
)。
django.utils.decorators
¶将函数装饰器转换为方法装饰器。它可以用来装饰方法或类;在后一种情况下,name
是要装饰的方法的名称,并且是必需的。
decorator
也可以是一个函数列表或元组。它们以相反的顺序包装,因此调用顺序是函数在列表/元组中出现的顺序。
参见 装饰基于类的视图 的用法示例。
给定一个中间件类,返回一个视图装饰器。这让你可以在每个视图的基础上使用中间件功能。中间件的创建不需要传递参数。
它假设中间件与 Django 1.9 和更早的老式中间件兼容(有 process_request()
、process_exception()
和 process_response()
等方法)。
像 decorator_from_middleware
一样,但是返回一个接受参数的函数,传递给 middleware_class。例如,cache_page()
装饰器是从 CacheMiddleware
中创建的,就像这样:
cache_page = decorator_from_middleware_with_args(CacheMiddleware)
@cache_page(3600)
def my_view(request):
pass
django.utils.encoding
¶返回一个代表任意对象 s
的 str
对象。使用 encoding
编解码器处理字节字符串。
如果 strings_only
是 True
,不要转换(一些)非字符串类对象。
确定对象实例是否属于一个受保护的类型。
当传递给 force_str(strings_only=True)
时,受保护类型的对象会被原样保存。
类似于 smart_str()
,除了惰性实例被解析为字符串,而不是作为惰性对象保存。
如果 strings_only
是 True
,不要转换(一些)非字符串类对象。
返回任意对象 s
的字节字符串版本,按照 encoding
中指定的编码。
如果 strings_only
是 True
,不要转换(一些)非字符串类对象。
类似于 smart_bytes
,除了惰性实例被解析为字节字符串,而不是作为惰性对象保存。
如果 strings_only
是 True
,不要转换(一些)非字符串类对象。
将国际化资源标识符(IRI)部分转换为适合包含在 URL 中的 URI 部分。
这是 RFC 3987 Section 3.1 中第 3.1 节的算法,由于假设输入是一个字符串而不是任意字节流,所以略作简化。
取一个 IRI(字符串或 UTF-8 字节)并返回一个包含编码结果的字符串。
将统一资源标识符转换为国际化资源标识符。
这是 RFC 3987 Section 3.2 第 3.2 节中的一个算法。
获取一个 ASCII 字节的 URI,并返回一个包含编码结果的字符串。
django.utils.feedgenerator
¶示例用法:
>>> from django.utils import feedgenerator
>>> feed = feedgenerator.Rss201rev2Feed(
... title="Poynter E-Media Tidbits",
... link="https://www.poynter.org/tag/e-media-tidbits/",
... description="A group blog by the sharpest minds in online media/journalism/publishing.",
... language="en",
... )
>>> feed.add_item(
... title="Hello",
... link="https://www.holovaty.com/test/",
... description="Testing.",
... )
>>> with open("test.rss", "w") as fp:
... feed.write(fp, "utf-8")
...
为了简化生成器的选择,使用 feedgenerator.DefaultFeed
,目前是 Rss201rev2Feed
。
关于不同版本的RSS的定义,参见: https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004/02/04/incompatible-rss。
创建一个 TagURI。
参见 https://web.archive.org/web/20110514113830/http://diveintomark.org/archives/2004/05/28/howto-atom-id
Stylesheet
¶Represents an RSS stylesheet.
An optional string containing the MIME type of the stylesheet. If not
specified, Django will attempt to guess it by using Python's
mimetypes.guess_type()
. Use mimetype=None
if you don't
want your stylesheet to have a MIME type specified.
An optional string which will be used as the media
attribute of
the stylesheet. Defaults to "screen"
. Use media=None
if you
don't want your stylesheet to have a media
attribute.
Enclosure
¶RssFeed
¶Rss201rev2Feed
¶RssUserland091Feed
¶Atom1Feed
¶django.utils.functional
¶@cached_property
装饰器将一个方法的结果缓存起来,该方法有一个 self
参数作为属性。只要实例存在,缓存的结果就会持续存在,所以如果实例被传来传去,并且随后函数被调用,缓存的结果就会被返回。
考虑一个典型的情况,在将模型实例放入上下文之前,视图可能需要调用模型的方法来执行一些计算,在上下文中,模板可能会再次调用该方法:
# the model
class Person(models.Model):
def friends(self):
# expensive computation
...
return friends
# in the view:
if person.friends():
...
而在模板中,你会有:
{% for friend in person.friends %}
在这里,friends()
将被调用两次。由于视图和模板中的实例 person
是一样的,所以用 @cached_property
来装饰 friends()
方法可以避免这种情况:
from django.utils.functional import cached_property
class Person(models.Model):
@cached_property
def friends(self): ...
请注意,由于该方法现在是一个属性,所以在 Python 代码中需要适当地访问它:
# in the view:
if person.friends:
...
缓存值可以像实例的普通属性一样对待:
# clear it, requiring re-computation next time it's called
person.__dict__.pop("friends", None)
# set a value manually, that will persist on the instance until cleared
person.friends = ["Huckleberry Finn", "Tom Sawyer"]
由于 描述符协议 的工作方式,在一个没有被访问过的 cached_property
上使用 del
(或 delattr
)会引起 AttributeError
。
除了提供潜在的性能优势外,@cached_property
还可以确保一个属性的值在一个实例的生命周期内不会发生意外变化。如果一个方法的计算是基于 datetime.now()
的,或者如果在同一实例上的一个方法的后续调用之间的短暂间隔中,变化被其他进程保存到数据库中,就可能发生这种情况。
你可以使用方法的缓存属性。例如,如果你有一个昂贵的 get_friends()
方法,并且想允许调用它而不检索缓存值,你可以编写:
friends = cached_property(get_friends)
虽然 person.get_friends()
会在每次调用时重新计算,但缓存属性的值会一直存在,直到你如上所述删除它为止:
x = person.friends # calls first time
y = person.get_friends() # calls again
z = person.friends # does not call
x is z # is True
与 @classmethod
类似,@classproperty
装饰器将带有单个 cls
参数的方法的结果转换为可以直接从类中访问的属性。
Django 提供了许多实用函数(特别是在 django.utils
中),这些函数将一个字符串作为它们的第一个参数,并对该字符串进行处理。这些函数可以被模板过滤器使用,也可以直接在其他代码中使用。
如果你自己编写类似的函数并处理翻译,你会面临这样一个问题:当第一个参数是一个惰性翻译对象时,该怎么办?你不想立即将其转换为字符串,因为你可能会在视图之外使用这个函数(因此当前线程的 locale 配置将不正确)。
对于这样的情况,可以使用 django.utils.functional.keep_lazy()
装饰器。它可以修改函数,使其在调用时,如果 参数是惰性翻译,则函数的执行会被延迟,直到需要将其转换为字符串。
例子:
from django.utils.functional import keep_lazy, keep_lazy_text
def fancy_utility_function(s, *args, **kwargs):
# Do some conversion on string 's'
...
fancy_utility_function = keep_lazy(str)(fancy_utility_function)
# Or more succinctly:
@keep_lazy(str)
def fancy_utility_function(s, *args, **kwargs): ...
keep_lazy()
装饰器需要一些额外的参数(*args
)来指定原始函数可以返回的类型。一个常见的用例是返回文本的函数。对于这些函数,你可以将 str
类型传递给 keep_lazy
(或者使用下一节描述的 keep_lazy_text()
装饰器)。
使用这个装饰器意味着你可以编写你的函数,并假设输入是一个正确的字符串,然后在最后添加对惰性翻译对象的支持。
keep_lazy(str)(func)
的快捷方式。
如果你有一个返回文本的函数,并且你希望能够在延迟其执行的同时接受惰性参数,你可以使用这个装饰器:
from django.utils.functional import keep_lazy, keep_lazy_text
# Our previous example was:
@keep_lazy(str)
def fancy_utility_function(s, *args, **kwargs): ...
# Which can be rewritten as:
@keep_lazy_text
def fancy_utility_function(s, *args, **kwargs): ...
django.utils.html
¶通常情况下,你应该使用 Django 的模板来构建 HTML,以利用它的自动转义机制,在适当的地方使用 django.utils.safestring
中的实用程序。这个模块提供了一些额外的低级实用程序来处理 HTML。
返回给定的文本,并对其的符号、引号和角括号进行编码,以便在 HTML 中使用。输入的内容首先被强制为一个字符串,输出的内容被应用了 mark_safe()
。
这类似于 str.format()
,但适用于构建 HTML 片段。第一个参数 format_string
不会被转义,但所有其他的参数和关键字参数在传递给 str.format()
之前都会通过 conditional_escape()
进行转义。最后,输出将应用 mark_safe()
。
对于构建小型 HTML 片段的情况,这个函数比直接使用 %
或 str.format()
进行字符串插值要好,因为它对所有参数都应用了转义 —— 就像模板系统默认应用转义一样。
所以,不要写:
mark_safe(
"%s <b>%s</b> %s"
% (
some_html,
escape(some_text),
escape(some_other_text),
)
)
你应该用:
format_html(
"{} <b>{}</b> {}",
mark_safe(some_html),
some_text,
some_other_text,
)
这样做的好处是,你不需要对每个参数应用 escape()
,如果你忘记了一个参数,就有可能出现错误和 XSS 漏洞。
请注意,虽然这个函数使用 str.format()
来进行内插,但 str.format()
提供的一些格式化选项(例如数字格式化)将无法使用,因为所有参数都通过 conditional_escape()
,而这个函数(最终)会调用 force_str()
来处理这些值。
Deprecated since version 5.0: 不推荐在不传递 args 或 kwargs 的情况下调用 format_html()
。
format_html()
的一个封装器,用于常见的情况,即一组参数需要使用相同的格式字符串进行格式化,然后使用 sep
加入。sep
也通过 conditional_escape()
传递。
args_generator
should be an iterator that yields arguments to pass to
format_html()
, either sequences of positional arguments or mappings of
keyword arguments.
For example, tuples can be used for positional arguments:
format_html_join(
"\n",
"<li>{} {}</li>",
((u.first_name, u.last_name) for u in users),
)
Or dictionaries can be used for keyword arguments:
format_html_join(
"\n",
'<li data-id="{id}">{id} {title}</li>',
({"id": b.id, "title": b.title} for b in books),
)
Support for mappings in args_generator
was added.
将所有 HTML/XML 特殊字符用它们的 Unicode 转义进行转义,以便将值安全地用于 JavaScript。还将转义后的 JSON 包装在一个 <script>
标签中。如果 element_id
参数不为 None
,则将传递的 id 分配给 <script>
标签。例如:
>>> json_script({"hello": "world"}, element_id="hello-data")
'<script id="hello-data" type="application/json">{"hello": "world"}</script>'
encoder
,默认为 django.core.serializers.json.DjangoJSONEncoder
,将用于序列化数据。关于这个序列化器的更多细节,请参见 JSON 序列化。
试图从字符串中删除任何类似 HTML 标签的内容,即包含在 <>
内的任何内容。
绝对不能保证结果的字符串是 HTML 安全的。所以千万不要在没有转义的情况下将 strip_tag
调用的结果标记为安全,例如使用 escape()
。
例子:
strip_tags(value)
如果 value
是 "<b>Joel</b> <button>is</button> a <span>slug</span>"
返回值将是 "Joel is a slug"
。
如果你正在寻找更强大的解决方案,考虑使用第三方的 HTML 清理工具。
类上的 __html__()
方法可以帮助非 Django 模板检测其输出不需要 HTML 转义的类。
这个装饰器通过在 mark_safe()
中封装 __str__()
来定义被装饰的类上的 __html__()
方法。确保 __str__()
方法确实返回不需要 HTML 转义的文本。
django.utils.http
¶Python 的 urllib.parse.urlencode()
函数的一个版本,可以对 MultiValueDict
和非字符串值进行操作。
将时间格式化为与 HTTP RFC 9110 Section 5.6.7 指定的 RFC 1123 Section 5.2.14 日期格式相匹配。
接受自 UTC 以来以秒为单位的浮点数,如 time.time()
输出的时间。如果设置为 None
,默认为当前时间。
输出格式为 Wdy, DD Mon YYYY HH:MM:SS GMT
的字符串。
django.utils.module_loading
¶用于处理 Python 模块的函数。
django.utils.safestring
¶用于处理 “安全字符串” 的函数和类:在 HTML 中无需进一步转义就可以安全显示的字符串。将某一字符串标记为 “安全字符串” 意味着该字符串的制作者已经将那些不应该被 HTML 引擎解释的字符(例如 '<')转化为适当的实体。
为(HTML)输出目的明确标记一个字符串为安全的。返回的对象可以用在任何适合字符串的地方。
可以在一个字符串上多次调用。
也可作为装饰器使用。
对于构建 HTML 片段,你通常应该使用 django.utils.html.format_html()
代替。
如果修改了被标记为安全的字符串,它将重新变为不安全。例如:
>>> mystr = "<b>Hello World</b> "
>>> mystr = mark_safe(mystr)
>>> type(mystr)
<class 'django.utils.safestring.SafeString'>
>>> mystr = mystr.strip() # removing whitespace
>>> type(mystr)
<type 'str'>
django.utils.text
¶一个 str.format()
用于 format_string
、args` 和/或 kwargs
包含惰性对象时的版本。第一个参数是要格式化的字符串。例如:
from django.utils.text import format_lazy
from django.utils.translation import pgettext_lazy
urlpatterns = [
path(
format_lazy("{person}/<int:pk>/", person=pgettext_lazy("URL", "person")),
PersonDetailView.as_view(),
),
]
这个例子允许翻译人员翻译部分 URL。如果 "person" 被翻译成 "persona",正则表达式将匹配 persona/(?P<pk>\d+)/$
,例如 persona/5/
。
通过以下方式将一个字符串转换为 URL slug。
如果 allow_unicode
为 False
(默认),则转换为 ASCII 码。
转换为小写。
删除非字母数字、下划线、连字符或空格的字符。
将任何空格或重复的破折号替换为单破折号。
移除前导和尾随的空格、破折号和下划线。
例如:
>>> slugify(" Joel is a slug ")
'joel-is-a-slug'
如果要允许 Unicode 字符,请传递 allow_unicode=True
。例如:
>>> slugify("你好 World", allow_unicode=True)
'你好-world'
django.utils.timezone
¶返回一个 tzinfo
实例,该实例表示一个与 UTC 有固定偏移的时区。
offset
是一个 datetime.timedelta
或一个整数分钟。UTC 以东的时区为正值,UTC 以西的时区为负值。
这是一个 Python 上下文管理器,它在进入时通过 activate()
设置 当前时区,并在退出时恢复之前的活动时区。如果 timezone
参数是 None
,则 当前时区 在进入时用 deactivate()
取消设置。
override
也可作为函数装饰器使用。
将一个感知的 datetime
转换为不同的时区,默认为 当前时区。
当省略 value
时,默认为 now()
。
这个函数不适用于 naive 的日期,请使用 make_aware()
代替。
使用 localtime()
将一个已知道的 datetime
转换为不同时区的 date()
,默认为 当前时区。
当省略 value
时,默认为 now()
。
此功能不适用于 naive 的日期。
django.utils.translation
¶关于以下用法的完整讨论,请参见 翻译文档。
标记要翻译的字符串,但现在不翻译它们。这可以用来存储全局变量中的字符串,这些字符串应该留在基础语言中(因为它们可能会被外部使用),并在以后被翻译。
翻译 singular
和 plural
,并根据 number
和 context
返回适当的字符串。
一个 Python 上下文管理器,它使用 django.utils.translation.activate()
获取给定语言的翻译对象,将其激活为当前线程的翻译对象,并在退出时重新激活之前的活动语言。如果 deactivate
参数为 True
,则可以用 django.utils.translation.deactivate()
在退出时停用临时翻译对象。如果传递 None
作为语言参数,则会在上下文中激活 NullTranslations()
实例。
override
也可作为函数装饰器使用。
返回当前选择的语言代码。如果翻译被暂时停用(通过 deactivate_all()
或当 None
被传递给 override()
时),返回 None
。
分析请求,找出用户希望系统显示的语言。只考虑 settings.LANGUAGES 中列出的语言。如果用户请求的是我们有主语言的子语言,我们会发送主语言。
如果 check_path
为 True
,则函数首先检查请求的 URL 的路径是否以 LANGUAGES
配置中列出的语言代码开头。
如果在 LANGUAGES
配置中,则返回 lang_code
,可能会选择一个更通用的变量。例如,如果 lang_code
是 'es-ar'
,并且 'es'
在 LANGUAGES
中,但 'es-ar'
没有,则返回 'es'
。
lang_code
的最大接受长度为 500 个字符。如果 lang_code
超过此限制且 strict
为 True
,或者如果没有通用变体且 strict
为 False
,则会引发 LookupError
。
如果 strict
是 False
(默认),当语言代码和通用变体都没有找到时,可能会返回一个特定国家的变体。例如,如果 LANGUAGES
中只有 'es-co'
,那么就会返回 lang_code
,如 'es'
和 'es-ar'
。如果 strict=True
,则不会返回这些匹配。
如果没有找到任何东西,会引发 LookupError
。
在旧版本中,超过 500 个字符的 lang_code
值会被处理而不会引发 LookupError
。
4月 27, 2025