Django 实用程序¶
本文档涵盖了 django.utils
中所有稳定的模块。django.utils
中的大部分模块都是为内部使用而设计的,只有以下部分可以被认为是稳定的,因此根据 内部发布废弃政策 的规定,这些模块可以向后兼容。
django.utils.cache
¶
这个模块包含了控制 HTTP 缓存的辅助函数。它通过管理响应的 Vary
头来实现。它包括直接对响应对象的头进行修补的函数,以及改变函数使其自己进行头修补的装饰器。
有关 Vary
标头的信息,请参阅 RFC 9110 Section 12.5.5。
本质上,Vary
HTTP 头定义了缓存在建立缓存密钥时应该考虑哪些头信息。如果请求的路径相同,但 Vary
中命名的头内容不同,则需要获得不同的缓存密钥,以防止传递错误的内容。
例如, 国际化 中间件需要通过 Accept-language
头来区分缓存。
- patch_cache_control(response, **kwargs)[source]¶
这个函数通过添加所有关键字参数来修补
Cache-Control
头。变化如下:所有的关键字参数名都转为小写,下划线转为连字符。
如果一个参数的值是
True
(确切地说是True
,而不仅仅是一个真值),那么只有参数名称会被添加到头。所有其他参数在应用
str()
后,都会加上其值。
- patch_response_headers(response, cache_timeout=None)[source]¶
为给定的
HttpResponse
对象添加一些有用的头信息。Expires
Cache-Control
每个头只有在还没有设置的情况下才会被添加。
cache_timeout
的单位是秒。默认使用CACHE_MIDDLEWARE_SECONDS
配置。
- add_never_cache_headers(response)[source]¶
在当前日期/时间上添加一个
Expires
标头。在响应中添加
Cache-Control: max-age=0, no-cache, no-store, must-revalidate, private
头,以表明页面永远不会被缓存。每个头只有在还没有设置的情况下才会被添加。
- patch_vary_headers(response, newheaders)[source]¶
在给定的
HttpResponse
对象中添加(或更新)Vary
标头。newheaders
是一个应该包含在Vary
中的标头名称列表。如果标头包含一个星号,那么根据 RFC 9110 Section 12.5.5,Vary
标头将由一个单独的星号'*'
组成。否则,不会删除Vary
中的现有标头。
django.utils.dateparse
¶
本模块中定义的函数共享以下属性:
它们接受 ISO 8601 日期/时间格式的字符串(或一些接近的替代格式),并从 Python 的
datetime
模块的相应类中返回对象。如果他们的输入格式很好,但不是有效的日期或时间,他们会引发
ValueError
。如果输入格式不好,则返回
None
。它们接受最多皮秒精度的输入,但它们将其截断为微秒,因为这是 Python 支持的。
- parse_date(value)[source]¶
解析一个字符串并返回一个
datetime.date
。
- parse_time(value)[source]¶
解析一个字符串并返回一个
datetime.time
。不支持 UTC 偏移;如果
value
描述的是 UTC 偏移,结果是None
。
- parse_datetime(value)[source]¶
解析一个字符串并返回一个
datetime.datetime
。支持 UTC 偏移;如果
value
描述的是 UTC 偏移,则结果的tzinfo
属性是一个datetime.timezone
实例。
- parse_duration(value)[source]¶
解析一个字符串并返回一个
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
¶
- method_decorator(decorator, name='')[source]¶
将函数装饰器转换为方法装饰器。它可以用来装饰方法或类;在后一种情况下,
name
是要装饰的方法的名称,并且是必需的。decorator
也可以是一个函数列表或元组。它们以相反的顺序包装,因此调用顺序是函数在列表/元组中出现的顺序。参见 装饰基于类的视图 的用法示例。
- decorator_from_middleware(middleware_class)[source]¶
给定一个中间件类,返回一个视图装饰器。这让你可以在每个视图的基础上使用中间件功能。中间件的创建不需要传递参数。
它假设中间件与 Django 1.9 和更早的老式中间件兼容(有
process_request()
、process_exception()
和process_response()
等方法)。
- decorator_from_middleware_with_args(middleware_class)[source]¶
像
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
¶
- smart_str(s, encoding='utf-8', strings_only=False, errors='strict')[source]¶
返回一个代表任意对象
s
的str
对象。使用encoding
编解码器处理字节字符串。如果
strings_only
是True
,不要转换(一些)非字符串类对象。
- is_protected_type(obj)[source]¶
确定对象实例是否属于一个受保护的类型。
当传递给
force_str(strings_only=True)
时,受保护类型的对象会被原样保存。
- force_str(s, encoding='utf-8', strings_only=False, errors='strict')[source]¶
类似于
smart_str()
,除了惰性实例被解析为字符串,而不是作为惰性对象保存。如果
strings_only
是True
,不要转换(一些)非字符串类对象。
- smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict')[source]¶
返回任意对象
s
的字节字符串版本,按照encoding
中指定的编码。如果
strings_only
是True
,不要转换(一些)非字符串类对象。
- force_bytes(s, encoding='utf-8', strings_only=False, errors='strict')[source]¶
类似于
smart_bytes
,除了惰性实例被解析为字节字符串,而不是作为惰性对象保存。如果
strings_only
是True
,不要转换(一些)非字符串类对象。
- iri_to_uri(iri)[source]¶
将国际化资源标识符(IRI)部分转换为适合包含在 URL 中的 URI 部分。
这是 RFC 3987 Section 3.1 中第 3.1 节的算法,由于假设输入是一个字符串而不是任意字节流,所以略作简化。
取一个 IRI(字符串或 UTF-8 字节)并返回一个包含编码结果的字符串。
- uri_to_iri(uri)[source]¶
将统一资源标识符转换为国际化资源标识符。
这是 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。
- get_tag_uri(url, date)[source]¶
创建一个 TagURI。
参见 https://web.archive.org/web/20110514113830/http://diveintomark.org/archives/2004/05/28/howto-atom-id
Enclosure
¶
RssFeed
¶
Rss201rev2Feed
¶
RssUserland091Feed
¶
Atom1Feed
¶
django.utils.functional
¶
- class cached_property(func)[source]¶
@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 del person.friends # or delattr(person, "friends") # 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
- class classproperty(method=None)[source]¶
与
@classmethod
类似,@classproperty
装饰器将带有单个cls
参数的方法的结果转换为可以直接从类中访问的属性。
- keep_lazy(func, *resultclasses)[source]¶
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_text(func)[source]¶
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。
- escape(text)[source]¶
返回给定的文本,并对其的符号、引号和角括号进行编码,以便在 HTML 中使用。输入的内容首先被强制为一个字符串,输出的内容被应用了
mark_safe()
。
- format_html(format_string, *args, **kwargs)[source]¶
这类似于
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_join(sep, format_string, args_generator)[source]¶
format_html()
的一个封装器,用于常见的情况,即一组参数需要使用相同的格式字符串进行格式化,然后使用sep
加入。sep
也通过conditional_escape()
传递。args_generator
应该是一个迭代器,返回args
的序列,这些序列将传递给format_html()
。例如:format_html_join("\n", "<li>{} {}</li>", ((u.first_name, u.last_name) for u in users))
- json_script(value, element_id=None, encoder=None)[source]¶
将所有 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 序列化。
- strip_tags(value)[source]¶
试图从字符串中删除任何类似 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_safe()[source]¶
类上的
__html__()
方法可以帮助非 Django 模板检测其输出不需要 HTML 转义的类。这个装饰器通过在
mark_safe()
中封装__str__()
来定义被装饰的类上的__html__()
方法。确保__str__()
方法确实返回不需要 HTML 转义的文本。
django.utils.http
¶
- urlencode(query, doseq=False)[source]¶
Python 的
urllib.parse.urlencode()
函数的一个版本,可以对MultiValueDict
和非字符串值进行操作。
- http_date(epoch_seconds=None)[source]¶
将时间格式化为与 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 引擎解释的字符(例如 '<')转化为适当的实体。
- mark_safe(s)[source]¶
为(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
¶
- format_lazy(format_string, *args, **kwargs)¶
一个
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/
。
- slugify(value, allow_unicode=False)[source]¶
通过以下方式将一个字符串转换为 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
¶
- get_fixed_timezone(offset)[source]¶
返回一个
tzinfo
实例,该实例表示一个与 UTC 有固定偏移的时区。offset
是一个datetime.timedelta
或一个整数分钟。UTC 以东的时区为正值,UTC 以西的时区为负值。
- override(timezone)[source]¶
这是一个 Python 上下文管理器,它在进入时通过
activate()
设置 当前时区,并在退出时恢复之前的活动时区。如果timezone
参数是None
,则 当前时区 在进入时用deactivate()
取消设置。override
也可作为函数装饰器使用。
- localtime(value=None, timezone=None)[source]¶
将一个感知的
datetime
转换为不同的时区,默认为 当前时区。当省略
value
时,默认为now()
。这个函数不适用于 naive 的日期,请使用
make_aware()
代替。
- localdate(value=None, timezone=None)[source]¶
使用
localtime()
将一个已知道的datetime
转换为不同时区的date()
,默认为 当前时区。当省略
value
时,默认为now()
。此功能不适用于 naive 的日期。
django.utils.translation
¶
关于以下用法的完整讨论,请参见 翻译文档。
- gettext_lazy(message)¶
- gettext_noop(message)[source]¶
标记要翻译的字符串,但现在不翻译它们。这可以用来存储全局变量中的字符串,这些字符串应该留在基础语言中(因为它们可能会被外部使用),并在以后被翻译。
- npgettext(context, singular, plural, number)[source]¶
翻译
singular
和plural
,并根据number
和context
返回适当的字符串。
- override(language, deactivate=False)[source]¶
一个 Python 上下文管理器,它使用
django.utils.translation.activate()
获取给定语言的翻译对象,将其激活为当前线程的翻译对象,并在退出时重新激活之前的活动语言。如果deactivate
参数为True
,则可以用django.utils.translation.deactivate()
在退出时停用临时翻译对象。如果传递None
作为语言参数,则会在上下文中激活NullTranslations()
实例。override
也可作为函数装饰器使用。
- get_language()[source]¶
返回当前选择的语言代码。如果翻译被暂时停用(通过
deactivate_all()
或当None
被传递给override()
时),返回None
。
- get_language_from_request(request, check_path=False)[source]¶
分析请求,找出用户希望系统显示的语言。只考虑 settings.LANGUAGES 中列出的语言。如果用户请求的是我们有主语言的子语言,我们会发送主语言。
如果
check_path
为True
,则函数首先检查请求的 URL 的路径是否以LANGUAGES
配置中列出的语言代码开头。
- get_supported_language_variant(lang_code, strict=False)[source]¶
如果在
LANGUAGES
配置中,则返回lang_code
,可能会选择一个更通用的变量。例如,如果lang_code
是'es-ar'
,并且'es'
在LANGUAGES
中,但'es-ar'
没有,则返回'es'
。lang_code
has a maximum accepted length of 500 characters. ALookupError
is raised iflang_code
exceeds this limit andstrict
isTrue
, or if there is no generic variant andstrict
isFalse
.如果
strict
是False
(默认),当语言代码和通用变体都没有找到时,可能会返回一个特定国家的变体。例如,如果LANGUAGES
中只有'es-co'
,那么就会返回lang_code
,如'es'
和'es-ar'
。如果strict=True
,则不会返回这些匹配。如果没有找到任何东西,会引发
LookupError
。Changed in Django 4.2.15:In older versions,
lang_code
values over 500 characters were processed without raising aLookupError
.