提交 7fe98f6f 编写于 作者: W wizardforcel

2017.2.15

上级 62ac1967
# 性能与优化
本文档提供的技术与工具概述,有助于使您的Django代码更高效,更快速,并使用更少系统资源。
## 简介
通常,人们首先关心的是编写的代码_起作用_,其逻辑函数根据需要产生预期输出。然而,有时,这将不足以使代码像我们希望的那样_有效地工作_。
Generally one’s first concern is to write code that works, whose logic functions as required to produce the expected output. Sometimes, however, this will not be enough to make the code work as efficiently as one would like.
## General approaches
### What are you optimizing _for_?
重要的是有一个清楚的想法你的意思是“性能”。它不只有一个指标。
改进的速度可能是程序最明显的目标,但有时可能会寻求其他性能改进,例如降低内存消耗或减少对数据库或网络的需求。
一个领域的改进往往会带来另一个领域的改进,但并不总是如此;有时甚至可以牺牲另一个。例如,程序速度的提高可能会导致程序使用更多的内存。更糟糕的是,它可以是自我毁灭 - 如果速度的改善是如此内存饥饿,系统开始耗尽内存,你会做更多的危害比好。
还有其他权衡要考虑。你自己的时间是宝贵的资源,比CPU时间更珍贵。一些改进可能太难以实现,或者可能影响代码的可移植性或可维护性。并非所有的性能改进都值得付出努力。
所以,你需要知道你的目标是什么性能改进,你还需要知道你有一个很好的理由,瞄准这个方向,因为你需要:
### Performance benchmarking
这是不好的只是猜测或假设在你的代码中低效率。
#### Django tools
[django-debug-toolbar](https://github.com/django-debug-toolbar/django-debug-toolbar/)是一个非常方便的工具,可以深入了解代码的工作以及它花费多少时间。特别是它可以显示你的页面生成的所有SQL查询,以及每个人花了多长时间。
第三方面板也可用于工具栏,可以(例如)报告缓存性能和模板呈现时间。
#### Third-party services
有一些免费服务将从远程HTTP客户端的角度分析和报告您的网站的页面的性能,实际上模拟实际用户的体验。
这些不能报告您的代码的内部,但可以提供有用的洞察您的网站的整体性能,包括不能从Django环境中充分测量的方面。示例包括:
* [雅虎Yslow](http://yslow.org/)
* [Google PageSpeed](https://developers.google.com/speed/pagespeed/)
还有一些付费服务执行类似的分析,包括一些是Django感知的,可以与您的代码库集成,以更广泛地分析其性能。
### Get things right from the start
一些优化工作涉及解决性能缺陷,但是有些工作可以简单地建立在你所做的工作中,作为你应该采取的良好做法的一部分,甚至在你开始考虑提高性能之前。
在这方面,Python是一个很好的语言,因为看起来优雅和感觉合适的解决方案通常是最好的表现。与大多数技能一样,学习什么“看起来正确”需要练习,但最有用的指南之一是:
#### Work at the appropriate level
Django提供了许多不同的方法来处理事情,但只是因为它可能以某种方式做某事并不意味着它是最合适的方式。例如,您可能会发现您可以计算同样的事情 - 集合中的项目数量,可能是在`QuerySet`中,在Python中,或在模板中。
但是,在较低级别而不是较高级别执行此工作几乎总是更快。在更高层次,系统必须通过多级抽象和多层机械来处理对象。
也就是说,数据库通常可以比Python更快地完成事情,这样做可以比模板语言更快:
```
# QuerySet operation on the database
# fast, because that's what databases are good at
my_bicycles.count()
# counting Python objects
# slower, because it requires a database query anyway, and processing
# of the Python objects
len(my_bicycles)
# Django template filter
# slower still, because it will have to count them in Python anyway,
# and because of template language overheads
{{ my_bicycles|length }}
```
一般来说,最适合的工作级别是最低级别的代码,它是舒适的。
注意
以上示例仅仅是说明性的。
首先,在现实情况下,您需要考虑在计数之前和之后发生的情况,以确定在特定上下文中执行_的最佳方式。_数据库优化文档描述了[_a case where counting in the template would be better_](db/optimization.html#overuse-of-count-and-exists)
其次,还有其他选择要考虑:在现实生活中,`{{ my_bicycles.count }} t0 >,它直接从模板调用`QuerySet` `count()`方法可能是最合适的选择。`
## Caching
通常,计算值是昂贵的(即资源匮乏和缓慢),因此将值保存到可快速访问的缓存中可以有巨大的好处,为下一次需要做好准备。
这是一个足够重要和强大的技术,Django包括一个综合的缓存框架,以及其他较小的缓存功能。
### [_The caching framework_](cache.html)
Django的[_caching framework_](cache.html)通过保存动态内容以便不需要为每个请求计算,从而为性能提升提供了非常重要的机会。
为了方便起见,Django提供了不同级别的缓存粒度:您可以缓存特定视图的输出,或仅缓存难以生成的片段,甚至整个网站。
实现缓存不应该被视为改进代码执行不良,因为它已被写得不好的替代方法。这是生产性能良好的代码的最后一步,而不是一个捷径。
### [`cached_property`](../ref/utils.html#django.utils.functional.cached_property "django.utils.functional.cached_property")
通常必须多次调用类实例的方法。如果这个功能是昂贵的,那么这样做可能是浪费。
使用`@cached_property`装饰器保存属性返回的值;下一次在该实例上调用函数时,它将返回保存的值,而不是重新计算它。请注意,这仅适用于将`self`作为其唯一参数的方法,并将方法更改为属性。
某些Django组件也有自己的缓存功能;这些在下面在与那些组件相关的部分中讨论。
## Understanding laziness
_懒惰_是对缓存的补充策略。缓存通过保存结果避免重新计算;延迟延迟计算,直到它实际需要。
懒惰允许我们在实例化之前,甚至在可能实例化它们之前引用它们。这有很多用途。
例如,可以在目标语言甚至已知之前使用[_lazy translation_](i18n/translation.html#lazy-translations),因为在实际需要翻译的字符串之前不发生,例如在呈现的模板中。
懒惰也是一种通过试图避免工作来节省努力的方式。也就是说,懒惰的一个方面是在做任何事情之前不做任何事情,因为它可能不是必然的。因此,懒惰可能具有性能影响,并且相关工作越昂贵,通过懒惰获得的就越多。
Python提供了许多用于延迟评估的工具,特别是通过[_generator_](https://docs.python.org/3/glossary.html#term-generator "(in Python v3.4)")[_generator expression_](https://docs.python.org/3/glossary.html#term-generator-expression "(in Python v3.4)")构造。值得一读的是Python中的懒惰,以便发现在代码中使用延迟模式的机会。
### Laziness in Django
Django本身相当懒惰。一个很好的例子可以在`QuerySets`的评估中找到。[_QuerySets are lazy_](db/queries.html#querysets-are-lazy)。因此,可以创建`QuerySet`,传递并与其他`QuerySets`组合,而不实际引发任何到数据库的访问以获取其描述的项目。传递的是`QuerySet`对象,而不是最终需要从数据库中获取的项目集合。
另一方面,[_certain operations will force the evaluation of a QuerySet_](../ref/models/querysets.html#when-querysets-are-evaluated)进行求值。避免对`QuerySet`的过早评估可以节省对数据库的昂贵且不必要的访问。
Django还提供了一个[`allow_lazy()`](../ref/utils.html#django.utils.functional.allow_lazy "django.utils.functional.allow_lazy")装饰器。这允许使用延迟参数调用的函数本身行为迟缓,只有在需要时才进行求值。因此,懒惰的论据 - 可能是一个昂贵的论点 - 不会被要求进行评估,直到它是严格要求。
## Databases
### [_Database optimization_](db/optimization.html)
Django的数据库层提供了各种方法来帮助开发人员从他们的数据库获得最佳性能。[_database optimization documentation_](db/optimization.html)汇集了相关文档的链接,并添加了各种提示,概述在尝试优化数据库使用情况时需要采取的步骤。
### Other database-related tips
启用[_Persistent connections_](../ref/databases.html#persistent-database-connections)可以加快连接到数据库帐户的请求处理时间的很大一部分。
这有助于在有限的网络性能的虚拟化主机上很多。
## HTTP performance
### Middleware
Django附带了一些有用的[_middleware_](../ref/middleware.html),可以帮助优化您的网站的性能。他们包括:
#### [`ConditionalGetMiddleware`](../ref/middleware.html#django.middleware.http.ConditionalGetMiddleware "django.middleware.http.ConditionalGetMiddleware")
添加了对现代浏览器的支持,可根据`ETag``Last-Modified`标头有条件地获取响应。
#### [`GZipMiddleware`](../ref/middleware.html#django.middleware.gzip.GZipMiddleware "django.middleware.gzip.GZipMiddleware")
压缩所有现代浏览器的响应,节省带宽和传输时间。请注意,GZipMiddleware目前被认为是一种安全风险,并且容易受到由TLS / SSL提供的保护无效的攻击。有关详细信息,请参阅[`GZipMiddleware`](../ref/middleware.html#django.middleware.gzip.GZipMiddleware "django.middleware.gzip.GZipMiddleware")中的警告。
### Sessions
#### [_Using cached sessions_](http/sessions.html#cached-sessions-backend)
[_Using cached sessions_](http/sessions.html#cached-sessions-backend)可能是一种通过消除从像数据库这样较慢的存储源加载会话数据而改为将经常使用的会话数据存储在内存中来提高性能的方法。
### Static files
静态文件,根据定义是不动态的,使优化增益的一个优秀的目标。
#### [`CachedStaticFilesStorage`](../ref/contrib/staticfiles.html#django.contrib.staticfiles.storage.CachedStaticFilesStorage "django.contrib.staticfiles.storage.CachedStaticFilesStorage")
通过利用Web浏览器的缓存能力,您可以在初始下载后完全消除给定文件的网络匹配。
[`CachedStaticFilesStorage`](../ref/contrib/staticfiles.html#django.contrib.staticfiles.storage.CachedStaticFilesStorage "django.contrib.staticfiles.storage.CachedStaticFilesStorage")会将一个内容相关标记附加到[_static files_](../ref/contrib/staticfiles.html)的文件名中,以确保浏览器能够安全地对其进行长期缓存,而不会丢失未来的更改 - 当文件更改时,将标记,所以浏览器将自动重新加载资产。
#### “Minification”
一些第三方Django工具和包提供了“缩小”HTML,CSS和JavaScript的能力。它们删除不必要的空格,换行符和注释,缩短变量名,从而减少您的网站发布的文档的大小。
## Template performance
注意:
* 使用`{% 阻止 %}`比使用`{% 包括 %}`
* 从许多小块组装的重碎片模板可能会影响性能
### The cached template loader
启用[`cached template loader`](../ref/templates/api.html#django.template.loaders.cached.Loader "django.template.loaders.cached.Loader")通常会大幅提高性能,因为它避免每次需要时编译每个模板渲染。
## Using different versions of available software
有时可能需要检查您使用的软件的不同和性能更好的版本是否可用。
这些技术针对的是更高级的用户,他们希望提高已经优化的Django站点的性能边界。
然而,他们不是性能问题的魔法解决方案,他们不可能比没有以更正确的方式做更基本的事情的网站带来更好的边际收益。
注意
值得重复的是:**达到您已经使用的软件的替代品永远不是性能问题的第一个答案**。当您达到这种优化水平时,您需要一个正式的基准解决方案。
### Newer is often - but not always - better
很少有新版本的维护良好的软件效率较低,但是维护者无法预期每一种可能的使用情况 - 因此,虽然知道较新的版本可能性能更好,但不要简单地假设它们一直会。
这是Django本身的真实。连续版本已在系统中提供了许多改进,但您仍应检查应用程序的真实性能,因为在某些情况下,您可能会发现这些更改意味着性能更差,而不是更好。
较新的Python版本以及Python软件包,往往会表现得更好 - 但测量,而不是假设。
注意
除非您在特定版本中遇到了异常的性能问题,否则在新版本中通常会找到更好的功能,可靠性和安全性,这些优点远远胜过您可能获胜或失败的任何性能。
### Alternatives to Django’s template language
对于几乎所有情况,Django的内置模板语言是完全足够的。然而,如果你的Django项目的瓶颈似乎在于模板系统,你已经用尽了其他机会来弥补这一点,第三方替代品可能是答案。
[Jinja2](http://jinja.pocoo.org/docs/)可以提高性能,特别是在速度方面。
替代模板系统在它们共享Django的模板语言的程度上有所不同。
注意
_如果_在模板中遇到性能问题,首先要做的是明白为什么。使用替代模板系统可能会更快,但是也可以获得相同的收益,而不会遇到麻烦 - 例如,您的模板中的昂贵的处理和逻辑可以更有效地在您的视图中。
### Alternative software implementations
可能值得检查你使用的Python软件是否已在不同的实现中提供,可以更快地执行相同的代码。
然而:编写良好的Django站点中的大多数性能问题不是在Python执行级别,而是在于低效的数据库查询,缓存和模板。如果你依赖写得不好的Python代码,你的性能问题不可能通过更快地执行来解决。
使用替代实现可能引入兼容性,部署,可移植性或维护问题。不言而喻,在采用非标准实施之前,您应该确保它为您的应用程序提供足够的性能增益,超过潜在的风险。
记住这些注意事项,您应该注意:
#### [PyPy](http://pypy.org/)
[PyPy](http://pypy.org/)是Python中Python本身的实现('标准'Python实现是在C中)。PyPy可以提供显着的性能提升,通常用于重量级应用。
PyPy项目的一个关键目标是与现有的Python API和库的[兼容性](http://pypy.org/compat.html)。Django是兼容的,但你需要检查你依赖的其他库的兼容性。
#### C implementations of Python libraries
一些Python库也在C中实现,可以更快。他们的目标是提供相同的API。注意兼容性问题和行为差异是未知的(并不总是立即明显)。
# Running Django on Jython
[Jython](http://www.jython.org/) 是在 Java 平台 (JVM) 运行的 Python 实现。这个文档将让你在Jython之上运行Django。
## Installing Jython
Django使用Jython 2.7b2及更高版本。有关下载和安装说明,请参阅[Jython](http://www.jython.org/)网站。
## Creating a servlet container
如果你只是想试验Django,请跳到下一节; Django包含一个可以用于测试的轻量级Web服务器,因此在准备在生产环境中部署Django之前,您不需要设置任何其他内容。
如果要在生产站点上使用Django,请使用Java servlet容器,例如[Apache Tomcat](http://tomcat.apache.org/)。如果您需要其包含的额外功能,则完整的JavaEE应用程序服务器(如[GlassFish](https://glassfish.java.net/)[JBoss](http://www.jboss.org/))也可以。
## Installing Django
下一步是安装Django本身。这与在标准Python上安装Django完全相同,因此请参阅[_Remove any old versions of Django_](../topics/install.html#removing-old-versions-of-django)[_Install the Django code_](../topics/install.html#install-django-code)以获取相关说明。
## Installing Jython platform support libraries
[django-jython](http://code.google.com/p/django-jython/)项目包含用于Django / Jython开发的数据库后端和管理命令。注意,内置的Django后端不会在Jython之上工作。
要安装它,请按照项目网站上详细的[安装说明](https://pythonhosted.org/django-jython/quickstart.html#install)操作。另外,阅读[数据库后端](https://pythonhosted.org/django-jython/database-backends.html)文档。
## Differences with Django on Jython
此时,Jython上的Django应该与运行在标准Python上的Django几乎相同。但是,有几点差异需要牢记:
* 请记住使用`jython`命令而不是`python`。文档使用`python`来保持一致性,但是如果你使用的是Jython,你会想每次发生时用`jython`来替代`python`
* 同样,您需要使用`JYTHONPATH`环境变量,而不是`PYTHONPATH`
* Django中需要[枕头](http://pillow.readthedocs.org/en/latest/)的任何部分都将无法工作。
# Porting to Python 3
第一个支持Python 3的版本是Django 1.5。感谢[six](http://pythonhosted.org/six/)的兼容层,无需对代码做出任何改动,就可以让你的代码同时在Python 2 (≥ 2.6.5)和Python 3 (≥ 3.2)上运行。
本文档主要针对希望支持Python 2和3的可插拔应用程序的作者。它还描述了适用于Django代码的指南。
## Philosophy
本文档假定您熟悉Python 2和Python 3之间的更改。如果你不是,请先阅读[Python的官方移植指南](https://docs.python.org/3/howto/pyporting.html)。刷新你对Python 2和3的unicode处理的知识将有所帮助; [Pragmatic Unicode](http://nedbatchelder.com/text/unipain.html)演示文稿是一个很好的资源。
Django使用_Python 2/3兼容源_策略。当然,你可以为自己的代码自由选择另一个策略,特别是如果你不需要保持与Python 2兼容。但是可插拔应用程序的作者鼓励使用与Django本身相同的移植策略。
如果您定位Python≥2.6,编写兼容的代码要容易得多。Django 1.5引入了诸如[`django.utils.six`](#module-django.utils.six "django.utils.six")之类的兼容性工具,它是[`six module`](http://pythonhosted.org/six/index.html#module-six "(in six v1.9)")的定制版本, 。为了方便起见,在Django 1.4.2中引入了向前兼容的别名。如果您的应用程序利用这些工具,它将需要Django≥1.4.2。
显然,编写兼容的源代码会增加一些开销,这会导致沮丧。Django的开发人员发现,尝试编写与Python 2兼容的Python 3代码比相反的更有意义。这不仅使你的代码更加面向未来,但Python 3的优势(如saner字符串处理)开始迅速发光。处理Python 2成为向后兼容性的要求,我们作为开发人员来处理这样的约束。
Django提供的移植工具受这种理念的启发,并且贯穿本指南。
## Porting tips
### Unicode literals
此步骤包括:
* 在Python模块顶部从 t> __未来__ 导入 unicode_literals添加`把它放在每个模块中,否则你会继续检查文件的顶部,看看哪个模式是有效的;`
* 在unicode字符串之前删除`u`前缀;
* 在bytestrings之前添加`b`前缀。
执行这些更改系统地保证向后兼容性。
然而,Django应用程序通常不需要bytestrings,因为Django只将unicode接口暴露给程序员。Python 3不鼓励使用bytestrings,二进制数据或面向字节的接口除外。Python 2使得bytestrings和unicode字符串可以有效地互换,只要它们只包含ASCII数据。利用这一点,尽可能使用unicode字符串,并避免`b`前缀。
注意
Python 2的`u`前缀是Python 3.2中的一个语法错误,但是由于 [**PEP 414**](http://www.python.org/dev/peps/pep-0414),它将再次允许在Python 3.3中。因此,如果您定位Python≥3.3,则此转换是可选的。它仍然推荐,按照“编写Python 3代码”的哲学。
### String handling
Python 2’s [unicode](https://docs.python.org/2/library/functions.html#unicode) type was renamed [`str`](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.4)") in Python 3, `str()` was renamed [`bytes`](https://docs.python.org/3/library/functions.html#bytes "(in Python v3.4)"), and [basestring](https://docs.python.org/2/library/functions.html#basestring) disappeared. [](http://pythonhosted.org/six/)提供[_tools_](#string-handling-with-six)来处理这些更改。
Django在[`django.utils.encoding`](../ref/utils.html#module-django.utils.encoding "django.utils.encoding: A series of helper functions to manage character encoding.")[`django.utils.safestring`](../ref/utils.html#module-django.utils.safestring "django.utils.safestring: Functions and classes for working with strings that can be displayed safely without further escaping in HTML.")模块中还包含多个与字符串相关的类和函数。他们的名字使用了`str`这个词,这在Python 2和Python 3以及`unicode`中并不是相同的,它在Python 3中不存在。为了避免歧义和混淆,这些概念重命名为`bytes``text`
以下是[`django.utils.encoding`](../ref/utils.html#module-django.utils.encoding "django.utils.encoding: A series of helper functions to manage character encoding.")中的名称更改:
| 旧名称 | 新名称 |
| --- | --- |
| `smart_str` | `smart_bytes` |
| `smart_unicode` | `smart_text` |
| `force_unicode` | `force_text` |
为了向后兼容,旧名称仍然适用于Python 2。在Python 3下,`smart_str``smart_text`的别名。
为了向前兼容性,新名称的工作原理与Django 1.4.2相同。
注意
[`django.utils.encoding`](../ref/utils.html#module-django.utils.encoding "django.utils.encoding: A series of helper functions to manage character encoding.")在Django 1.5中被重构,以提供更一致的API。检查其文档以获取更多信息。
[`django.utils.safestring`](../ref/utils.html#module-django.utils.safestring "django.utils.safestring: Functions and classes for working with strings that can be displayed safely without further escaping in HTML.")主要通过[`mark_safe()`](../ref/utils.html#django.utils.safestring.mark_safe "django.utils.safestring.mark_safe")[`mark_for_escaping()`](../ref/utils.html#django.utils.safestring.mark_for_escaping "django.utils.safestring.mark_for_escaping")函数使用,但没有更改。如果你使用的内部,这里是名称更改:
| 旧名称 | 新名称 |
| --- | --- |
| `EscapeString` | `EscapeBytes` |
| `EscapeUnicode` | `EscapeText` |
| `SafeString` | `SafeBytes` |
| `SafeUnicode` | `SafeText` |
为了向后兼容,旧名称仍然适用于Python 2。在Python 3下,`EscapeString``SafeString`分别是`EscapeText``SafeText`的别名。
为了向前兼容性,新名称的工作原理与Django 1.4.2相同。
### [`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)") and [__unicode__()](https://docs.python.org/2/reference/datamodel.html#object.__unicode__) methods
在Python 2中,对象模型指定[`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)")[__unicode __()](https://docs.python.org/2/reference/datamodel.html#object.__unicode__)方法。如果这些方法存在,它们必须分别返回`str`(bytes)和`unicode`(text)。
`print`语句和[`str`](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.4)")内置调用[`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)")来确定对象的人类可读表示。`unicode`内置调用[__unicode __()](https://docs.python.org/2/reference/datamodel.html#object.__unicode__)如果存在,否则返回[`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)"),并使用系统编码。相反,[`Model`](../ref/models/instances.html#django.db.models.Model "django.db.models.Model")基类通过编码为UTF-8自动从[__unicode __()](https://docs.python.org/2/reference/datamodel.html#object.__unicode__)中导出[`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)")
在Python 3中,只有[`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)"),它必须返回`str`(text)。
(也可以定义[`__bytes__()`](https://docs.python.org/3/reference/datamodel.html#object.__bytes__ "(in Python v3.4)"),但Django应用程序对该方法几乎没有用处,因为它们几乎不处理`bytes`。)
Django provides a simple way to define [`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)") and [__unicode__()](https://docs.python.org/2/reference/datamodel.html#object.__unicode__) methods that work on Python 2 and 3: you must define a [`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)") method returning text and to apply the [`python_2_unicode_compatible()`](../ref/utils.html#django.utils.encoding.python_2_unicode_compatible "django.utils.encoding.python_2_unicode_compatible") decorator.
在Python 3上,装饰器是一个无操作。在Python 2中,它定义了适当的[__unicode __()](https://docs.python.org/2/reference/datamodel.html#object.__unicode__)[`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)")方法(替换过程中的原始[`__str__()`](https://docs.python.org/3/reference/datamodel.html#object.__str__ "(in Python v3.4)")方法)。这里有一个例子:
```
from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class MyClass(object):
def __str__(self):
return "Instance of my class"
```
这种技术是Django移植理念的最佳匹配。
对于向前兼容性,此装饰器可用于Django 1.4.2。
最后,请注意,[`__repr__()`](https://docs.python.org/3/reference/datamodel.html#object.__repr__ "(in Python v3.4)")必须在所有版本的Python上返回`str`
### [`dict`](https://docs.python.org/3/library/stdtypes.html#dict "(in Python v3.4)") and [`dict`](https://docs.python.org/3/library/stdtypes.html#dict "(in Python v3.4)")-like classes
[`dict.keys()`](https://docs.python.org/3/library/stdtypes.html#dict.keys "(in Python v3.4)")[`dict.items()`](https://docs.python.org/3/library/stdtypes.html#dict.items "(in Python v3.4)")[`dict.values()`](https://docs.python.org/3/library/stdtypes.html#dict.values "(in Python v3.4)")返回列表在Python 2和迭代器在Python 3。[`QueryDict`](../ref/request-response.html#django.http.QueryDict "django.http.QueryDict")和在[`django.utils.datastructures`](../ref/utils.html#module-django.utils.datastructures "django.utils.datastructures: Data structures that aren't in Python's standard library.")中定义的[`dict`](https://docs.python.org/3/library/stdtypes.html#dict "(in Python v3.4)")
[six](http://pythonhosted.org/six/) provides compatibility functions to work around this change: [`iterkeys()`](http://pythonhosted.org/six/index.html#six.iterkeys "(in six v1.9)"), [`iteritems()`](http://pythonhosted.org/six/index.html#six.iteritems "(in six v1.9)"), and [`itervalues()`](http://pythonhosted.org/six/index.html#six.itervalues "(in six v1.9)"). 它还包含未正式记录的`iterlists`函数,适用于`django.utils.datastructures.MultiValueDict`及其子类。
### [`HttpRequest`](../ref/request-response.html#django.http.HttpRequest "django.http.HttpRequest") and [`HttpResponse`](../ref/request-response.html#django.http.HttpResponse "django.http.HttpResponse") objects
根据 [**PEP 3333**](http://www.python.org/dev/peps/pep-3333)
* 头总是`str`对象,
* 输入和输出流始终为`bytes`对象。
具体来说,[`HttpResponse.content`](../ref/request-response.html#django.http.HttpResponse.content "django.http.HttpResponse.content")包含`bytes`,如果您在测试中将其与`str`进行比较,则可能会出现问题。首选解决方案是依靠[`assertContains()`](testing/tools.html#django.test.SimpleTestCase.assertContains "django.test.SimpleTestCase.assertContains")[`assertNotContains()`](testing/tools.html#django.test.SimpleTestCase.assertNotContains "django.test.SimpleTestCase.assertNotContains")。这些方法接受响应和unicode字符串作为参数。
## Coding guidelines
以下准则在Django的源代码中强制实施。它们也推荐用于遵循相同移植策略的第三方应用程序。
### Syntax requirements
#### Unicode
在Python 3中,默认情况下所有字符串都被视为Unicode。来自Python 2的`unicode`类型在Python 3中称为`str``str`变为`bytes`
您不能在unicode字符串字面量之前使用`u`前缀,因为它在Python 3.2中是语法错误。必须使用`b`前缀字节字符串。
为了在Python 2中启用相同的行为,每个模块必须从`__future__`导入`unicode_literals`
```
from __future__ import unicode_literals
my_string = "This is an unicode literal"
my_bytestring = b"This is a bytestring"
```
如果您需要Python 2下的字节字符串字符串和Python 3下的Unicode字符串字符串,请使用[`str`](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.4)") builtin:
```
str('my string')
```
在Python 3中,`str``bytes`之间没有任何自动转换,而且[`codecs`](https://docs.python.org/3/library/codecs.html#module-codecs "(in Python v3.4)")模块变得更加严格。[`str.encode()`](https://docs.python.org/3/library/stdtypes.html#str.encode "(in Python v3.4)")始终返回`bytes``bytes.decode`始终返回`str`。因此,有时需要以下模式:
```
value = value.encode('ascii', 'ignore').decode('ascii')
```
如果您必须[索引bytestrings](https://docs.python.org/3/howto/pyporting.html#indexing-bytes-objects),请谨慎。
#### Exceptions
捕获异常时,使用`as`关键字:
```
try:
...
except MyException as exc:
...
```
这个旧的语法在Python 3中被删除:
```
try:
...
except MyException, exc: # Don't do that!
...
```
使用不同跟踪重新处理异常的语法也发生了更改。使用[`six.reraise()`](http://pythonhosted.org/six/index.html#six.reraise "(in six v1.9)")
### Magic methods
使用下面的模式来处理在Python 3中重命名的魔法方法。
#### Iterators
```
class MyIterator(six.Iterator):
def __iter__(self):
return self # implement some logic here
def __next__(self):
raise StopIteration # implement some logic here
```
#### Boolean evaluation
```
class MyBoolean(object):
def __bool__(self):
return True # implement some logic here
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
```
#### Division
```
class MyDivisible(object):
def __truediv__(self, other):
return self / other # implement some logic here
def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)
def __itruediv__(self, other):
return self // other # implement some logic here
def __idiv__(self, other): # Python 2 compatibility
return type(self).__itruediv__(self, other)
```
在类上而不是在实例上查找特殊的方法来反映Python解释器的行为。
### Writing compatible code with six
[six](http://pythonhosted.org/six/)是在单个代码库中支持Python 2和3的规范兼容性库。阅读它的文档!
A [`customized version of six`](#module-django.utils.six "django.utils.six") is bundled with Django as of version 1.4.2\. 您可以将其导入为`django.utils.six`
以下是编写兼容代码所需的最常见更改。
#### String handling
在Python 3中删除了`basestring``unicode`类型,并改变了`str`的含义。要测试这些类型,请使用以下习语:
```
isinstance(myvalue, six.string_types) # replacement for basestring
isinstance(myvalue, six.text_type) # replacement for unicode
isinstance(myvalue, bytes) # replacement for str
```
Python≥2.6提供`bytes`作为`str`的别名,因此您不需要[`six.binary_type`](http://pythonhosted.org/six/index.html#six.binary_type "(in six v1.9)")
#### `long`
`long`类型在Python 3中不再存在。`1L`是语法错误。使用[`six.integer_types`](http://pythonhosted.org/six/index.html#six.integer_types "(in six v1.9)")检查值是整数还是长整型:
```
isinstance(myvalue, six.integer_types) # replacement for (int, long)
```
#### `xrange`
如果在Python 2上使用`xrange`,请导入`six.moves.range`并使用它。您还可以导入`six.moves.xrange`(它等同于`six.moves.range`),但第一种方法允许您在删除对Python 2的支持时。
#### Moved modules
一些模块在Python 3中重命名。`django.utils.six.moves`模块(基于[`six.moves module`](http://pythonhosted.org/six/index.html#module-six.moves "(in six v1.9)"))提供了兼容的位置以导入它们。
#### PY2
如果您需要在Python 2和Python 3中使用不同的代码,请检查[`six.PY2`](http://pythonhosted.org/six/index.html#six.PY2 "(in six v1.9)")
```
if six.PY2:
# compatibility code for Python 2
```
这是最后的解决方案,当[`six`](http://pythonhosted.org/six/index.html#module-six "(in six v1.9)")不提供适当的功能。
### Django customized version of six
与Django捆绑在一起的六个版本(`django.utils.six`)包含一些仅供内部使用的自定义项。
# Python 的兼容性
Django 的目的,是要与多个不同的 Python 版本兼容。
\ No newline at end of file
此差异已折叠。
# 静态文件应用
`django.contrib.staticfiles` 从你的应用(和其他你指定的地方)收集所有静态文件到同一个地方,这样产品就能很容易的被维护
看看这里
对于静态文件的应用和一些用法示例的介绍,请参阅[_管理静态文件(CSS,图像) _](../../howto/static-files/index.html). 如果你想知道如何部署静态文件, 请参阅 [_部署静态文件_](../../howto/static-files/deployment.html).
## 设置
查看[_staticfiles settings_](../settings.html#settings-staticfiles)了解更多设置细节
* [STATIC_ROOT](../settings.html#std:setting-STATIC_ROOT)
* [STATIC_URL](../settings.html#std:setting-STATIC_URL)
* [STATICFILES_DIRS](../settings.html#std:setting-STATICFILES_DIRS)
* [STATICFILES_STORAGE](../settings.html#std:setting-STATICFILES_STORAGE)
* [STATICFILES_FINDERS](../settings.html#std:setting-STATICFILES_FINDERS)
## 管理命令
`django.contrib.staticfiles` 公开三个管理命令
### 搜集静态文件
`django-admin collectstatic`
搜集静态文件到 [`STATIC_ROOT`](../settings.html#std:setting-STATIC_ROOT).
默认情况下,重复文件名以类似于模板分辨率工作原理的方式解析:将使用首先在指定位置之一找到的文件。如果您感到困惑,[`findstatic`](#django-admin-findstatic)命令可以帮助您显示找到的文件。
使用[`enabled finders`](../settings.html#std:setting-STATICFILES_FINDERS)搜索文件。默认值是查看由[`STATICFILES_DIRS`](../settings.html#std:setting-STATICFILES_DIRS)中定义的所有位置以及在由[`INSTALLED_APPS`](../settings.html#std:setting-INSTALLED_APPS)设置指定的应用程序的`'static'`目录中定义的所有位置。
[`collectstatic`](#django-admin-collectstatic)管理命令在每次运行后调用[`STATICFILES_STORAGE`](../settings.html#std:setting-STATICFILES_STORAGE)[`post_process()`](#django.contrib.staticfiles.storage.StaticFilesStorage.post_process "django.contrib.staticfiles.storage.StaticFilesStorage.post_process")方法,并传递管理所发现的路径列表命令。它还接收[`collectstatic`](#django-admin-collectstatic)的所有命令行选项。默认情况下,它由[`CachedStaticFilesStorage`](#django.contrib.staticfiles.storage.CachedStaticFilesStorage "django.contrib.staticfiles.storage.CachedStaticFilesStorage")使用。
默认情况下,收集的文件从[`FILE_UPLOAD_PERMISSIONS`](../settings.html#std:setting-FILE_UPLOAD_PERMISSIONS)接收权限,收集的目录从[`FILE_UPLOAD_DIRECTORY_PERMISSIONS`](../settings.html#std:setting-FILE_UPLOAD_DIRECTORY_PERMISSIONS)接收权限。如果您希望对这些文件和/或目录使用不同的权限,可以暂存[_static files storage classes_](#staticfiles-storages),并指定`file_permissions_mode`和/或`directory_permissions_mode`例如:
```
from django.contrib.staticfiles import storage
class MyStaticFilesStorage(storage.StaticFilesStorage):
def __init__(self, *args, **kwargs):
kwargs['file_permissions_mode'] = 0o640
kwargs['directory_permissions_mode'] = 0o760
super(MyStaticFilesStorage, self).__init__(*args, **kwargs)
```
然后将[`STATICFILES_STORAGE`](../settings.html#std:setting-STATICFILES_STORAGE)设置为`'path.to.MyStaticFilesStorage'`
New in Django 1.7:
覆盖`file_permissions_mode``directory_permissions_mode`的功能是Django 1.7中的新功能。以前,文件权限始终使用[`FILE_UPLOAD_PERMISSIONS`](../settings.html#std:setting-FILE_UPLOAD_PERMISSIONS)和始终使用的目录权限[`FILE_UPLOAD_DIRECTORY_PERMISSIONS`](../settings.html#std:setting-FILE_UPLOAD_DIRECTORY_PERMISSIONS)
一些常用的选项是:
`--noinput`
不要提示用户输入任何类型。
`-i` `<pattern>`
`--ignore` `<pattern>`
忽略与此glob样式模式匹配的文件或目录。使用多次忽略更多。
`-n`
`--dry-run`
除了修改文件系统之外,执行所有操作。
`-c`
`--clear`
在尝试复制或链接原始文件之前清除现有文件。
`-l`
`--link`
创建指向每个文件的符号链接,而不是复制。
`--no-post-process`
不要调用配置的[`STATICFILES_STORAGE`](../settings.html#std:setting-STATICFILES_STORAGE)存储后端的[`post_process()`](#django.contrib.staticfiles.storage.StaticFilesStorage.post_process "django.contrib.staticfiles.storage.StaticFilesStorage.post_process")方法。
`--no-default-ignore`
不要忽略常见的私有glob样式模式`'CVS'``'.*'``'*~'`
有关选项的完整列表,请参阅命令自己的帮助,运行:
```
$ python manage.py collectstatic --help
```
### findstatic
`django-admin findstatic`
使用已启用的查找器搜索一个或多个相对路径。
例如:
```
$ python manage.py findstatic css/base.css admin/js/core.js
Found 'css/base.css' here:
/home/special.polls.com/core/static/css/base.css
/home/polls.com/core/static/css/base.css
Found 'admin/js/core.js' here:
/home/polls.com/src/django/contrib/admin/media/js/core.js
```
默认情况下,找到所有匹配的位置。要仅返回每个相对路径的第一个匹配,请使用`--first`选项:
```
$ python manage.py findstatic css/base.css --first
Found 'css/base.css' here:
/home/special.polls.com/core/static/css/base.css
```
这是一个调试助手;它会显示给定路径将收集哪个静态文件。
通过将[`--verbosity`](../django-admin.html#django-admin-option---verbosity)标志设置为0,可以抑制额外的输出,只需获取路径名称:
```
$ python manage.py findstatic css/base.css --verbosity 0
/home/special.polls.com/core/static/css/base.css
/home/polls.com/core/static/css/base.css
```
另一方面,通过将[`--verbosity`](../django-admin.html#django-admin-option---verbosity)标志设置为2,可以获取所有搜索的目录:
```
$ python manage.py findstatic css/base.css --verbosity 2
Found 'css/base.css' here:
/home/special.polls.com/core/static/css/base.css
/home/polls.com/core/static/css/base.css
Looking in the following locations:
/home/special.polls.com/core/static
/home/polls.com/core/static
/some/other/path/static
```
New in Django 1.7:
添加了搜索其目录的其他输出。
### runserver
`django-admin runserver`
Overrides the core [`runserver`](../django-admin.html#django-admin-runserver) command if the `staticfiles` app is [`installed`](../settings.html#std:setting-INSTALLED_APPS) and adds automatic serving of static files and the following new options.
`--nostatic`
使用`--nostatic`选项可以完全禁止使用应用程序提供静态文件。仅当应用位于项目的[`INSTALLED_APPS`](../settings.html#std:setting-INSTALLED_APPS)设置中时,此选项才可用。
用法示例:
```
django-admin runserver --nostatic
```
`--insecure`
使用`--insecure`选项强制使用应用程式提供静态档案,即使[`DEBUG`](../settings.html#std:setting-DEBUG)设定为`False`通过使用此功能,您可以确认**严重无效**以及可能**不安全**。这只适用于本地开发,应**从不用于生产**,并且仅当应用程序位于项目的[`INSTALLED_APPS`](../settings.html#std:setting-INSTALLED_APPS)设置时可用。[`runserver`](../django-admin.html#django-admin-runserver)`--insecure`不适用于[`CachedStaticFilesStorage`](#django.contrib.staticfiles.storage.CachedStaticFilesStorage "django.contrib.staticfiles.storage.CachedStaticFilesStorage")
用法示例:
```
django-admin runserver --insecure
```
## 存储
### StaticFilesStorage
_class_ `storage.``StaticFilesStorage`
使用[`STATIC_ROOT`](../settings.html#std:setting-STATIC_ROOT)设置作为基本文件系统位置和[`STATIC_URL`](../settings.html#std:setting-STATIC_URL)设置的[`FileSystemStorage`](../files/storage.html#django.core.files.storage.FileSystemStorage "django.core.files.storage.FileSystemStorage")存储后端的子类分别作为基本URL。
`storage.StaticFilesStorage.``post_process`(_paths_, _**options_)
此方法在每次运行后由[`collectstatic`](#django-admin-collectstatic)管理命令调用,并将找到的文件的本地存储和路径作为字典以及命令行选项传递。
[`CachedStaticFilesStorage`](#django.contrib.staticfiles.storage.CachedStaticFilesStorage "django.contrib.staticfiles.storage.CachedStaticFilesStorage")在幕后使用它来替换路径与它们的哈希对等体,并适当地更新缓存。
### ManifestStaticFilesStorage
New in Django 1.7.
_class_ `storage.``ManifestStaticFilesStorage`
[`StaticFilesStorage`](#django.contrib.staticfiles.storage.StaticFilesStorage "django.contrib.staticfiles.storage.StaticFilesStorage")存储后端的子类,通过将文件内容的MD5哈希附加到文件名来存储它处理的文件名。例如,文件`css/styles.css`也将另存为`css/styles.55e7cbb9ba48.css`
此存储的目的是为了在一些页面仍然引用这些文件的情况下继续提供旧文件,例如。因为它们由您或第三方代理服务器缓存。此外,如果您希望将[远期Expires标头](https://developer.yahoo.com/performance/rules.html#expires)应用于已部署的文件,以加快后续网页访问的加载时间,这将非常有帮助。
存储后端会自动使用缓存副本的路径(使用[`post_process()`](#django.contrib.staticfiles.storage.StaticFilesStorage.post_process "django.contrib.staticfiles.storage.StaticFilesStorage.post_process")方法)替换保存的文件中与其他已保存文件匹配的路径。默认情况下,用于查找这些路径(`django.contrib.staticfiles.storage.HashedFilesMixin.patterns`)的正则表达式涵盖[@import](http://www.w3.org/TR/CSS2/cascade.html#at-import)规则和[url() / t3>](http://www.w3.org/TR/CSS2/syndata.html#uri) [级联样式表](http://www.w3.org/Style/CSS/)的语句。例如,`'css/styles.css'`文件带有内容
```
@import url("../admin/css/base.css");
```
将替换为调用`ManifestStaticFilesStorage`存储后端的[`url()`](../files/storage.html#django.core.files.storage.Storage.url "django.core.files.storage.Storage.url")方法,最终保存一个`'css/styles.55e7cbb9ba48.css'`具有以下内容:
```
@import url("../admin/css/base.27e20196a850.css");
```
要启用`ManifestStaticFilesStorage`,您必须确保满足以下要求:
* [`STATICFILES_STORAGE`](../settings.html#std:setting-STATICFILES_STORAGE)设置设置为`'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'`
* [`DEBUG`](../settings.html#std:setting-DEBUG)设置为`False`
* 您可以使用`staticfiles` [`static`](#std:templatetag-staticfiles-static)模板标记来引用模板中的静态文件
* 您已使用[`collectstatic`](#django-admin-collectstatic)管理命令收集了所有静态文件
由于创建MD5哈希值会对运行时的网站造成负担,因此`staticfiles`会自动将所有已处理文件的哈希值映射存储在名为`staticfiles.json` 。当您运行[`collectstatic`](#django-admin-collectstatic)管理命令时,会发生这种情况。
由于运行[`collectstatic`](#django-admin-collectstatic)的要求,在运行测试时,通常不应使用此存储器,因为`collectstatic`不作为正常测试设置的一部分运行。在测试期间,请确保[`STATICFILES_STORAGE`](../settings.html#std:setting-STATICFILES_STORAGE)设置设置为像`'django.contrib.staticfiles.storage.StaticFilesStorage'`(默认值)。
`storage.ManifestStaticFilesStorage.``file_hash`(_name_, _content=None_)
创建文件的散列名称时使用的方法。需要返回给定文件名和内容的哈希值。默认情况下,它从内容的块计算MD5哈希,如上所述。随意覆盖此方法使用自己的哈希算法。
### CachedStaticFilesStorage
_class_ `storage.``CachedStaticFilesStorage`
`CachedStaticFilesStorage`类似于[`ManifestStaticFilesStorage`](#django.contrib.staticfiles.storage.ManifestStaticFilesStorage "django.contrib.staticfiles.storage.ManifestStaticFilesStorage")类,但使用Django的[_caching framework_](../../topics/cache.html)来存储处理文件的哈希名称,而不是静态清单文件`staticfiles.json`。这在您无权访问文件系统的情况下非常有用。
如果要覆盖存储使用的高速缓存后端的某些选项,只需在名为`'staticfiles'`[`CACHES`](../settings.html#std:setting-CACHES)设置中指定自定义条目即可。它会回到使用`'default'`缓存后端。
## 模板标签
### 静态的
使用配置的[`STATICFILES_STORAGE`](../settings.html#std:setting-STATICFILES_STORAGE)存储来为给定的相对路径创建完整的网址,例如:
```
{% load static from staticfiles %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />
```
上一个示例等于使用`"images/hi.jpg"`调用[`STATICFILES_STORAGE`](../settings.html#std:setting-STATICFILES_STORAGE)实例的`url`方法。这在使用非本地存储后端部署文件时特别有用,如[_Serving static files from a cloud service or CDN_](../../howto/static-files/deployment.html#staticfiles-from-cdn)提供静态文件中所述。
如果您希望在不显示静态网址的情况下检索静态网址,则可以使用略有不同的调用:
```
{% load static from staticfiles %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}" alt="Hi!" />
```
## 查找模块
`staticfiles`查找器具有`searched_locations`属性,它是查找器搜索的目录路径的列表。用法示例:
```
from django.contrib.staticfiles import finders
result = finders.find('css/base.css')
searched_locations = finders.searched_locations
```
New in Django 1.7.
已添加`searched_locations`属性。
## 其他帮助
除了[`staticfiles`](#module-django.contrib.staticfiles "django.contrib.staticfiles: An app for handling static files.")应用程序之外还有一些其他助手可以使用静态文件:
* [`django.template.context_processors.static()`](../templates/api.html#django.template.context_processors.static "django.template.context_processors.static")上下文处理器,将[`STATIC_URL`](../settings.html#std:setting-STATIC_URL)添加到用[`RequestContext`](../templates/api.html#django.template.RequestContext "django.template.RequestContext")上下文渲染的每个模板上下文。
* 内置模板标记[`static`](../templates/builtins.html#std:templatetag-static),它接受一个路径,并使用静态前缀[`STATIC_URL`](../settings.html#std:setting-STATIC_URL)将其链接。
* 内置模板标记[`get_static_prefix`](../templates/builtins.html#std:templatetag-get_static_prefix)用于将模板变量填充为静态前缀[`STATIC_URL`](../settings.html#std:setting-STATIC_URL)以用作变量或直接。
* 类似的模板标签[`get_media_prefix`](../templates/builtins.html#std:templatetag-get_media_prefix),其工作方式类似于[`get_static_prefix`](../templates/builtins.html#std:templatetag-get_static_prefix),但使用[`MEDIA_URL`](../settings.html#std:setting-MEDIA_URL)
### 静态文件开发视图
静态文件工具主要用于帮助将静态文件成功部署到生产环境中。这通常意味着一个单独的,专用的静态文件服务器,这在开发本地时是很麻烦的开销。因此,`staticfiles`应用程序附带了一个**快速和脏的帮助视图**,您可以使用它在开发中本地提供文件。
`views.``serve`(_request_, _path_)
此视图函数在开发中提供静态文件。
警告
此视图仅在[`DEBUG`](../settings.html#std:setting-DEBUG)`True`时有效。
这是因为此视图**严重无效**,可能**不安全**。这只适用于本地开发,应**从不用于生产**
Changed in Django 1.7:
[`DEBUG`](../settings.html#std:setting-DEBUG)`False`时,此视图现在将引发[`Http404`](../../topics/http/views.html#django.http.Http404 "django.http.Http404")异常而不是[`ImproperlyConfigured`](../exceptions.html#django.core.exceptions.ImproperlyConfigured "django.core.exceptions.ImproperlyConfigured")
注意
要猜测提供的文件的内容类型,此视图依赖于来自Python标准库的[`mimetypes`](https://docs.python.org/3/library/mimetypes.html#module-mimetypes "(in Python v3.4)")模块,该模块本身依赖于底层平台的映射文件。如果您发现此视图没有为特定文件返回正确的内容类型,则很可能是平台的地图文件需要更新。这可以通过在Debian发行版上安装或更新Red Hat发行版上的`mailcap`软件包或`mime-support`来实现。
此视图由[`runserver`](../django-admin.html#django-admin-runserver)自动启用([`DEBUG`](../settings.html#std:setting-DEBUG)设置为`True`)。要使用不同本地开发服务器的视图,请将以下代码段添加到主URL配置的末尾:
```
from django.conf import settings
from django.contrib.staticfiles import views
if settings.DEBUG:
urlpatterns += [
url(r'^static/(?P<path>.*)$', views.serve),
]
```
注意,模式(`r'^ static /'`)的开头应该是你的[`STATIC_URL`](../settings.html#std:setting-STATIC_URL)设置。
由于这有点麻烦,还有一个帮助函数,将为你做这个:
`urls.``staticfiles_urlpatterns`()
这将返回正确的URL模式,用于将静态文件提供给已定义的模式列表。使用它像这样:
```
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# ... the rest of your URLconf here ...
urlpatterns += staticfiles_urlpatterns()
```
这将检查您的[`STATIC_URL`](../settings.html#std:setting-STATIC_URL)设置,并将视图连接到相应的静态文件。不要忘记适当地设置[`STATICFILES_DIRS`](../settings.html#std:setting-STATICFILES_DIRS)设置,让`django.contrib.staticfiles`知道除了应用程序目录中的文件之外还要查找文件的位置。
警告
只有[`DEBUG`](../settings.html#std:setting-DEBUG) 设置为 `True` ,并且 [`STATIC_URL`](../settings.html#std:setting-STATIC_URL) 设置不为空和完整的URL路径,比如 `http://static.example.com/`,这个帮助功能才会工作。
这是因为该视图 **效率不高** 并且很可能 **不安全**. 该视图仅适用于本地开发 ,而**不应该用于项目实际生产环境**.
### Specialized test case to support ‘live testing’
_class_ `testing.``StaticLiveServerTestCase`
这个单元测试TestCase子类扩展[`django.test.LiveServerTestCase`](../../topics/testing/tools.html#django.test.LiveServerTestCase "django.test.LiveServerTestCase")
就像它的父类,你可以使用它来编写测试,涉及运行测试中的代码,并使用 HTTP测试工具(例如 Selenium,PhantomJS 等),因为它需要同时发布静态素材。
但是考虑到它使用了上面描述的[`django.contrib.staticfiles.views.serve()`](#django.contrib.staticfiles.views.serve "django.contrib.staticfiles.views.serve")视图,它可以在测试执行时透明地覆盖由`staticfiles` finders。这意味着您不需要在测试设置之前或作为测试设置的一部分运行[`collectstatic`](#django-admin-collectstatic)
New in Django 1.7:
`StaticLiveServerTestCase`是Django 1.7中的新功能。以前,它的功能由[`django.test.LiveServerTestCase`](../../topics/testing/tools.html#django.test.LiveServerTestCase "django.test.LiveServerTestCase")提供。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# django.contrib.webdesign
自版本1.8后已弃用:程序包仅包含一个模板标记,并已移至内置标记([`lorem`](../templates/builtins.html#std:templatetag-lorem))。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# Django安全
这份文档是 Django 的安全功能的概述。 它包括给 Django 驱动的网站一些加固建议。
## 跨站脚本&nbsp;(XSS) 防护
## 跨站脚本 (XSS) 防护
XSS攻击允许用户注入客户端脚本到其他用户的浏览器里。 这通常是通过存储在数据库中的恶意脚本,它将检索并显示给其他用户,或者通过让用户点击一个链接,这将导致攻击者的 JavaScript 被用户的浏览器执行。 然而,XSS 攻击可以来自任何不受信任的源数据,如 Cookie 或 Web 服务,任何没有经过充分处理就包含在网页中的数据。
使用 Django 模板保护你免受多数 XSS 攻击。 然而,重要的是要了解它提供了什么保护及其局限性。
Django 模板会[_ 编码特殊字符 _](../ref/templates/language.html#automatic-html-escaping) ,这些字符在 HTML 中都是特别危险的。 虽然这可以防止大多数恶意输入的用户,但它不能完全保证万无一失。 例如,它不会防护以下内容:
Django 模板会[ _编码特殊字符_ ](../ref/templates/language.html#automatic-html-escaping),这些字符在 HTML 中都是特别危险的。 虽然这可以防止大多数恶意输入的用户,但它不能完全保证万无一失。 例如,它不会防护以下内容:
```
<style class=>...</style>
......@@ -23,7 +25,7 @@ Django 模板会[_ 编码特殊字符 _](../ref/templates/language.html#automati
你也应该在数据库中存储 HTML 的时候要非常小心,尤其是当 HTML 被检索然后展示出来。
## 跨站请求伪造&nbsp;(CSRF) 防护
## 跨站请求伪造 (CSRF) 防护
CSRF 攻击允许恶意用户在另一个用户不知情或者未同意的情况下,以他的身份执行操作。
......@@ -31,7 +33,7 @@ Django 对大多数类型的 CSRF 攻击有内置的保护,在适当情况下
[_CSRF 防护_](../ref/csrf.html#how-csrf-works) 是通过检查每个 POST 请求的一个随机数(nonce)来工作。 这确保了恶意用户不能简单“回放”你网站上面表单的POST,以及让另一个登录的用户无意中提交表单。恶意用户必须知道这个随机数,它是用户特定的(存在cookie里)。
使用&nbsp;[_HTTPS_](#security-recommendation-ssl)来部署的时候,`CsrfViewMiddleware`会检查HTTP referer协议头是否设置为同源的URL(包括子域和端口)。因为HTTPS提供了附加的安全保护,转发不安全的连接请求时,必须确保链接使用 HTTPS,并使用HSTS支持的浏览器。
使用 [_HTTPS_](#security-recommendation-ssl)来部署的时候,`CsrfViewMiddleware`会检查HTTP referer协议头是否设置为同源的URL(包括子域和端口)。因为HTTPS提供了附加的安全保护,转发不安全的连接请求时,必须确保链接使用 HTTPS,并使用HSTS支持的浏览器。
使用`csrf_exempt`装饰器来标记视图时,要非常小心,除非这是极其必要的。
......@@ -45,19 +47,19 @@ SQl注入是一种攻击类型,恶意用户可以在系统数据库中执行
点击劫持是一类攻击,恶意站点在一个frame中包裹了另一个站点。这类攻击可能导致用户被诱导在目标站点做出一些无意识的行为。
Django在[`X-Frame-Options 中间件`](../ref/middleware.html#django.middleware.clickjacking.XFrameOptionsMiddleware "django.middleware.clickjacking.XFrameOptionsMiddleware")的表单中中含有&nbsp;[_点击劫持保护 _](../ref/clickjacking.html#clickjacking-prevention),它在支持的浏览器中可以保护站点免于在frame中渲染。也可以在每个视图中禁止这一保护,或者配置要发送的额外的协议头。
Django在[`X-Frame-Options 中间件`](../ref/middleware.html#django.middleware.clickjacking.XFrameOptionsMiddleware "django.middleware.clickjacking.XFrameOptionsMiddleware")的表单中中含有 [_点击劫持保护_ ](../ref/clickjacking.html#clickjacking-prevention),它在支持的浏览器中可以保护站点免于在frame中渲染。也可以在每个视图中禁止这一保护,或者配置要发送的额外的协议头。
对于任何不需要将页面包装在三方站点的frame中,或者只需要包含它的一部分的站点,都强烈推荐启用这一中间件。
## SSL/HTTPS
## SSL / HTTPS
把你的站点部署在HTTPS下总是更安全的,尽管在所有情况下不都有效。如果不这样,恶意的网络用户可能会嗅探授权证书,或者其他在客户端和服务端之间传输的信息,或者一些情况下 --&nbsp;**活跃的**网络攻击者 -- 会修改在两边传输的数据。
把你的站点部署在HTTPS下总是更安全的,尽管不是在所有情况下都有效。如果不这样,恶意的网络用户可能会嗅探授权证书,或者其他在客户端和服务端之间传输的信息,或者一些情况下 -- **活跃的**网络攻击者 -- 会修改在两边传输的数据。
如果你想要使用HTTPS提供的保护,并且在你的服务器上开启它,你需要遵循一些额外的步骤:
如果你想要HTTPS提供保护,那么需要在你的服务器上启用它,可能还需要去做一些额外的操作
* 如果必要的话,设置 [`SECURE_PROXY_SSL_HEADER`](../ref/settings.html#std:setting-SECURE_PROXY_SSL_HEADER),确保你已经彻底了解警告。未能实现它会导致CSRF方面的缺陷,也是很危险的!
* 设置重定向,以便HTTP下的请求可以重定向到HTTPS。
* 设置重定向,那样通过HTTP的请求会重定向到HTTPS。
这可以通过自定义的中间件来实现。请注意[`SECURE_PROXY_SSL_HEADER`](../ref/settings.html#std:setting-SECURE_PROXY_SSL_HEADER)下的警告。对于反向代理的情况,配置web主服务器来重定向到HTTPS或许是最简单也许是最安全的做法。
......@@ -73,17 +75,17 @@ Django在[`X-Frame-Options 中间件`](../ref/middleware.html#django.middleware.
在某些情况下,Django使用客户端提供的`Host` 协议头来构造URL。虽然这些值可以被审查,来防止跨站脚本攻击(XSS),但是一个假的`Host`值可以用于跨站请求伪造(CSRF),有害的缓存攻击,以及email中的有害链接。
Because even seemingly-secure web server configurations are susceptible to fake `Host` headers, Django validates `Host` headers against the [`ALLOWED_HOSTS`](../ref/settings.html#std:setting-ALLOWED_HOSTS) setting in the [`django.http.HttpRequest.get_host()`](../ref/request-response.html#django.http.HttpRequest.get_host "django.http.HttpRequest.get_host") method.
因为即使表面上看起来安全的web服务器也容易被篡改`主机头`,Django再次在django.http.HttpRequest.get_host()这个方法中验证主机头这个ALLOWED_HOSTS的设置 Django validates `Host` headers against the [`ALLOWED_HOSTS`](../ref/settings.html#std:setting-ALLOWED_HOSTS) setting in the [`django.http.HttpRequest.get_host()`](../ref/request-response.html#django.http.HttpRequest.get_host "django.http.HttpRequest.get_host") method.
验证只通过[`get_host()`](../ref/request-response.html#django.http.HttpRequest.get_host "django.http.HttpRequest.get_host")来应用;如果你的代码从`request.META`中直接访问`Host`协议头,就会绕开这一安全防护。
详见完整的[`ALLOWED_HOSTS`](../ref/settings.html#std:setting-ALLOWED_HOSTS)文档。
Warning
警告
Previous versions of this document recommended configuring your web server to ensure it validates incoming HTTP `Host` headers. While this is still recommended, in many common web servers a configuration that seems to validate the `Host` header may not in fact do so. For instance, even if Apache is configured such that your Django site is served from a non-default virtual host with the `ServerName` set, it is still possible for an HTTP request to match this virtual host and supply a fake `Host` header. Thus, Django now requires that you set [`ALLOWED_HOSTS`](../ref/settings.html#std:setting-ALLOWED_HOSTS) explicitly rather than relying on web server configuration.
本文档的先前版本建议配置Web服务器以确保其验证传入的HTTP `Host`头。虽然这仍然是建议,在许多常见的Web服务器,似乎验证`Host`头的配置可能实际上不这样做。例如,即使Apache配置为使您的Django站点从设置了`ServerName`的非默认虚拟主机提供,HTTP请求仍然可以匹配此虚拟主机并提供假`Host`标头。因此,Django现在要求您明确设置[`ALLOWED_HOSTS`](../ref/settings.html#std:setting-ALLOWED_HOSTS),而不是依赖于Web服务器配置。
另外,就像1.3.1,如果你的配置需要它的话,Django 需要你显式开启对`X-Forwarded-Host` 协议头的支持(通过 [`USE_X_FORWARDED_HOST`](../ref/settings.html#std:setting-USE_X_FORWARDED_HOST) 这只)。
另外,就像1.3.1,如果你的配置需要它的话,Django 需要你显式开启对`X-Forwarded-Host` 协议头的支持(通过 [`USE_X_FORWARDED_HOST`](../ref/settings.html#std:setting-USE_X_FORWARDED_HOST) 设置)。
## Session 会话安全
......@@ -99,11 +101,11 @@ Previous versions of this document recommended configuring your web server to en
* 如果你自己处理静态文件,确保像Apache的`mod_php`的处理器已关闭,它会将静态文件执行为代码。你并不希望用户能够通过上传和请求一个精心构造的文件来执行任意代码。
* Django’s media upload handling poses some vulnerabilities when that media is served in ways that do not follow security best practices. Specifically, an HTML file can be uploaded as an image if that file contains a valid PNG header followed by malicious HTML. This file will pass verification of the library that Django uses for [`ImageField`](../ref/models/fields.html#django.db.models.ImageField "django.db.models.ImageField") image processing (Pillow). When this file is subsequently displayed to a user, it may be displayed as HTML depending on the type and configuration of your web server.
* 当媒体以不遵循安全最佳做法的方式提供时,Django的媒体上传处理带来一些漏洞。具体来说,如果HTML文件包含有效的PNG标头,然后是恶意HTML,则可以将其上传为图片。此文件将通过对Django用于[`ImageField`](../ref/models/fields.html#django.db.models.ImageField "django.db.models.ImageField")图像处理(Pillow)的库的验证。当此文件随后显示给用户时,可能会显示为HTML,具体取决于Web服务器的类型和配置。
No bulletproof technical solution exists at the framework level to safely validate all user uploaded file content, however, there are some other steps you can take to mitigate these attacks:
在框架级别上没有安全验证所有用户上传的文件内容的防弹技术解决方案,但是,还可以采取一些其他步骤来减轻这些攻击:
* One class of attacks can be prevented by always serving user uploaded content from a distinct top-level or second-level domain. This prevents any exploit blocked by [same-origin policy](http://en.wikipedia.org/wiki/Same-origin_policy) protections such as cross site scripting. For example, if your site runs on `example.com`, you would want to serve uploaded content (the [`MEDIA_URL`](../ref/settings.html#std:setting-MEDIA_URL) setting) from something like `usercontent-example.com`. It’s _not_ sufficient to serve content from a subdomain like `usercontent.example.com`.
1. 通过始终提供来自不同顶级或二级域的用户上传的内容,可以防止一类攻击。这可以防止受到[同源策略](http://en.wikipedia.org/wiki/Same-origin_policy)保护(例如跨站点脚本)阻止的任何漏洞利用。For example, if your site runs on `example.com`, you would want to serve uploaded content (the [`MEDIA_URL`](../ref/settings.html#std:setting-MEDIA_URL) setting) from something like `usercontent-example.com`. _不_足以提供来自`usercontent.example.com`等子网域的内容。
2. 除此之外,应用可以选择为用户上传的文件定义一个允许的文件扩展名的白名单,并且配置web服务器直处理这些文件。
## 额外的安全话题
......@@ -116,8 +118,3 @@ Previous versions of this document recommended configuring your web server to en
* 秘密保存[`SECRET_KEY`](../ref/settings.html#std:setting-SECRET_KEY)
* 使用防火墙来限制缓存系统和数据库的访问是个好主意。
> 译者:[Django 文档协作翻译小组](http://python.usyiyi.cn/django/index.html),原文:[Security overview](https://docs.djangoproject.com/en/1.8/topics/security/)。
>
> 本文以 [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 协议发布,转载请保留作者署名和文章出处。
>
> [Django 文档协作翻译小组](http://python.usyiyi.cn/django/index.html)人手紧缺,有兴趣的朋友可以加入我们,完全公益性质。交流群:467338606。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# Django 中文文档 1.8 #
译者:[Django 文档协作翻译小组](http://python.usyiyi.cn/django/index.html),来源:[Django documentation](https://docs.djangoproject.com/en/1.8/)
译者:[Django 文档协作翻译小组](http://python.usyiyi.cn/django/index.html),来源:[Django documentation](https://docs.djangoproject.com/en/1.8/),最后更新:2017.2.15
本文档以 [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 协议发布,转载请保留作者署名和文章出处。
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册