2015年4月1日
欢迎来到Django 1.8!
这些发行说明涵盖新功能以及一些向后不兼容更改,您需要知道从Django 1.7或更早版本升级时。我们还开始了对某些功能的弃用过程,某些功能已达到其弃用过程的结束,已删除。
Django 1.8已被指定为Django的第二个“Long-Term Support” (LTS)版本。它将在其发布后至少三年内收到安全更新。支持以前的LTS,Django 1.4,将从发布Django 1.8的6个月结束。
与Django 1.7一样,Django 1.8需要Python 2.7或更高版本,但我们强烈推荐最新的小版本。
Django现在有一个用于Model._meta的正式API,它提供了正式支持的retrieve fields和基于它们的attributes。
从0.96“魔法删除”之前的日子开始,Model._meta对象已经成为Django的一部分 - 它不是一个官方的,稳定的API。在认识到这一点,我们努力在可能的情况下保持与旧的API端点的向后兼容性。但是,不是新的官方API一部分的API端点已被弃用,最终将被删除。已提供guide to migrating from the old API to the new API的指南。
Django 1.8定义了一个用于集成模板后端的稳定API。它包括对Django模板语言和Jinja2的内置支持。它支持在同一项目中使用多个引擎渲染模板。有关详情,请参阅topic guide中的新功能,并查看upgrade instructions。
Several features of the django-secure third-party library have been integrated into Django. django.middleware.security.SecurityMiddleware为请求/响应周期提供了几种安全增强功能。check命令的新--deploy选项允许您检查生产设置文件,以了解如何提高站点的安全性。
Django现在有一个具有PostgreSQL特定功能扩展的模块,如ArrayField,HStoreField,Range Fields和unaccent功能的完整细目可在文档中找到in the documentation
Query Expressions允许您创建,自定义和组合复杂的SQL表达式。这已启用注释接受除聚合以外的表达式。聚合现在能够引用多个字段,以及执行算术,类似于F()对象。order_by() has also gained the ability to accept expressions.
Conditional Expressions允许您在查询中使用if ... elif ... else
database functions的集合也包括在诸如Coalesce,Concat和Substr等功能中。
TestCase已重构,以允许在类级别使用事务和保存点进行数据初始化。不支持事务的数据库后端,例如MySQL和MyISAM存储引擎,仍然能够运行这些测试,但不会从改进中受益。测试现在在两个嵌套的atomic()块中运行:一个用于整个类,一个用于每个测试。
警告
除了本节中概述的更改外,请务必查看已删除的任何功能的deprecation plan。如果您没有在指定功能的弃用时间轴内更新代码,则其移除可能会显示为向后不兼容的更改。
将未保存的对象分配给ForeignKey,GenericForeignKey和OneToOneField现在会引发一个ValueError。
以前,未保存的对象的分配将被忽略。例如:
>>> book = Book.objects.create(name="Django")
>>> book.author = Author(name="John")
>>> book.author.save()
>>> book.save()
>>> Book.objects.get(name="Django")
>>> book.author
>>>
现在,将出现一个错误,以防止数据丢失:
>>> book.author = Author(name="john")
Traceback (most recent call last):
...
ValueError: Cannot assign "<Author: John>": "Author" instance isn't saved in the database.
如果您需要允许分配未保存的实例(旧行为),并且不关心数据丢失的可能性(例如,您从不将对象保存到数据库),可以使用allow_unsaved_instance_assignment属性禁用此检查。
If you have written a custom management command that only accepts positional arguments and you didn’t specify the args command variable, you might get an error like Error: unrecognized arguments: ..., as variable parsing is now based on argparse which doesn’t implicitly accept positional arguments. You can make your command backwards compatible by simply setting the args class variable. 但是,如果您不必与旧的Django版本保持兼容性,最好按照Writing custom django-admin commands中所述实施新的add_arguments()方法。
通过测试运行器将自定义参数添加到test管理命令的方法已更改。以前,您可以在测试运行器上提供option_list类变量,以添加更多参数(àla optparse)。Now to implement the same behavior, you have to create an add_arguments(cls, parser) class method on the test runner and call parser.add_argument to add any custom arguments, as parser is now an argparse.ArgumentParser instance.
长度超过数据库支持的列名称长度的字段名称可能会产生问题。例如,使用MySQL,您将遇到创建列的异常,而使用PostgreSQL,列名称将被数据库截断(您可能会在PostgreSQL日志中看到警告)。
已经引入了模型检查,以在实际创建数据库表之前更好地警告用户此场景。
如果你有一个现有的模型,其中这个检查似乎是一个假阳性,例如在PostgreSQL的名称已经被截断,只需使用db_column指定正在使用的名称。
该检查也适用于在隐式ManyToManyField.through模型中生成的列。如果遇到问题,请使用through创建显式模型,然后根据需要在其列上指定db_column。
查询模型查找现在将检查传递的对象是否为正确类型,如果不是,则会引发ValueError。以前,Django不在乎对象是否是正确的类型;它只是使用对象的相关字段属性(例如。id)。现在,会出现一个错误,以防止不正确的查找:
>>> book = Book.objects.create(name="Django")
>>> book = Book.objects.filter(author=book)
Traceback (most recent call last):
...
ValueError: Cannot query "<Book: Django>": Must be "Author" instance.
旧的默认75个字符max_length无法存储所有可能的符合RFC3696 / 5321的电子邮件地址。为了存储所有可能有效的电子邮件地址,max_length已增加到254个字符。您需要为受影响的模型生成和应用数据库迁移(如果您希望保留当前字段的长度,请添加max_length=75)。包括django.contrib.auth.models.User.email的迁移。
2014年7月,对于PostgreSQL 8.4,上游支持期结束。因此,Django 1.8将9.0设置为它正式支持的最小PostgreSQL版本。
这也包括删除对PostGIS 1.3和1.4的支持,因为这些版本不支持在晚于8.4的PostgreSQL版本。
Django现在还需要使用Psycopg2版本2.4.5或更高版本(如果您要使用django.contrib.postgres),则需要使用2.5+。
上游支持期限的结束在2012年1月到达MySQL 5.0和2013年12月的MySQL 5.1。因此,Django 1.8将5.5设置为它正式支持的最小MySQL版本。
对于Oracle 9.2,2012年1月为Oracle 10.1,以及2013年7月为Oracle 10.2,上游支持期结束于2010年7月。因此,Django 1.8将11.1设置为它正式支持的最低Oracle版本。
早期版本的Django将CONNECT和RESOURCE角色授予Oracle上的测试用户。这些角色已被弃用,因此Django 1.8使用特定的底层特权。这将更改主用户运行测试所需的特权(除非将项目配置为避免创建测试用户)。现在所需的确切权限在Oracle notes中有详细说明。
现在,AbstractUser.last_login字段允许空值。以前,它默认为创建用户的时间,如果用户从未登录,这是误导。如果您使用默认用户(django.contrib.auth.models.User),请运行contrib.auth中包含的数据库迁移。
如果您使用的是继承自AbstractUser的自定义用户模型,则需要运行makemigrations并为包含该模型的应用生成迁移。此外,如果希望为未登录的用户将last_login设置为NULL,则可以运行此查询:
from django.db import models
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractBaseUser
UserModel = get_user_model()
if issubclass(UserModel, AbstractBaseUser):
UserModel._default_manager.filter(
last_login=models.F('date_joined')
).update(last_login=None)
TemplateResponse构造函数旨在作为render()函数的插入替换。但是,它有一点点不兼容,因为对于TemplateResponse,来自传递的上下文字典的上下文数据可能被从上下文处理器返回的上下文数据所覆盖,而对于render是另一种方式。这是一个错误,render的行为更合适,因为它允许全局定义的上下文处理器在视图中被本地覆盖。如果您依赖事实上下文数据,则可以使用上下文处理器覆盖TemplateResponse中的上下文数据,您需要更改代码。
装饰器override_settings()和modify_settings()现在用作类装饰器时在类级别。因此,当覆盖setUpClass()或tearDownClass()时,应始终调用super实现。
formtools contrib应用程序已移动到单独的包中。django.contrib.formtools本身已被移除。文档提供migration instructions。
新包可以在Github和PyPI上找到。
Django先前在TestCase中关闭了每个测试之间的数据库连接。这不再是这样的,因为Django现在在一个事务中包装整个TestCase。如果你的一些测试依赖于旧的行为,你应该让它们继承自TransactionTestCase。
如果您一直依赖于django.template模块中公开的私有API,则可能需要从django.template.base导入它们。
还有私有API django.template.base.compile_string(),django.template.loader.find_template()和django.template.loader.get_template_from_string()已删除。
在早期版本的Django中,在具有反向外键关系的模型上(例如),model._meta.get_all_related_objects()将关系作为django.db.models.related.RelatedObject与model属性设置为关系的源。现在,此方法返回django.db.models.fields.related.ManyToOneRel(私有API RelatedObject已删除)和model源模型可以在related_model属性上访问。
考虑Django 1.8中的教程中的这个例子:
>>> p = Poll.objects.get(pk=1)
>>> p._meta.get_all_related_objects()
[<ManyToOneRel: polls.choice>]
>>> p._meta.get_all_related_objects()[0].model
<class 'polls.models.Poll'>
>>> p._meta.get_all_related_objects()[0].related_model
<class 'polls.models.Choice'>
并将其与旧版本的行为进行比较:
>>> p._meta.get_all_related_objects()
[<RelatedObject: polls:choice related to poll>]
>>> p._meta.get_all_related_objects()[0].model
<class 'polls.models.Choice'>
要访问源模型,可以使用这样的模式来编写将与Django 1.8和旧版本一起使用的代码:
for relation in opts.get_all_related_objects():
to_model = getattr(relation, 'related_model', relation.model)
另请注意,get_all_related_objects()在1.8中已弃用。有关新API,请参见upgrade guide。
记录了对数据库后端API的以下更改,以帮助编写第三方后端更新其代码:
BaseDatabaseXXX类已移至django.db.backends.base。请从新位置导入它们:
from django.db.backends.base.base import BaseDatabaseWrapper
from django.db.backends.base.client import BaseDatabaseClient
from django.db.backends.base.creation import BaseDatabaseCreation
from django.db.backends.base.features import BaseDatabaseFeatures
from django.db.backends.base.introspection import BaseDatabaseIntrospection
from django.db.backends.base.introspection import FieldInfo, TableInfo
from django.db.backends.base.operations import BaseDatabaseOperations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.backends.base.validation import BaseDatabaseValidation
data_types,data_types_suffix和data_type_check_constraints属性已从DatabaseCreation类转移到DatabaseWrapper
SQLCompiler.as_sql()方法现在采用subquery参数(#24164)。
BaseDatabaseOperations.date_interval_sql()方法现在只需要一个timedelta参数。
为了使得在使用Python代码调用HTML时“输出HTML”时输出HTML的内置模板过滤器,django.template.defaultfilters中的以下函数已更改为自动转义其输入值:
如果您要传递信任的内容,可以通过指定autoescape=False来还原为旧的行为。在模板中使用相应的过滤器时,此更改不会有任何影响。
作为Model._meta API(从django.db.models.options.Options类)的形式化的一部分,一些方法已被弃用,在Django 2.0中删除:
已提供migration guide来协助将您的代码从旧的API转换为新的官方API。
Django 1.6 introduced {% load cycle from future %} and {% load firstof from future %} syntax for forward compatibility of the cycle and firstof template tags. 此语法现已弃用,将在Django 2.0中删除。You can simply remove the {% load ... from future %} tags.
在Django的旧日,鼓励在urlpatterns中将视图引用为字符串:
urlpatterns = patterns('',
url('^$', 'myapp.views.myview'),
)
Django会在内部神奇地导入myapp.views.myview,并将该字符串转换为真正的函数引用。为了在引用来自同一模块的许多视图时减少重复,patterns()函数需要一个所需的初始prefix参数,该参数附加到所有视图该组urlpatterns:
urlpatterns = patterns('myapp.views',
url('^$', 'myview'),
url('^other/$', 'otherview'),
)
在现代时代,我们更新了教程,建议您直接导入视图模块并引用视图函数(或类)。这有一些优点,所有这些都源于我们使用普通Python代替“Django String Magic”:当你输入视图名称时出现的错误不那么模糊,IDE可以帮助自动完成视图名称等。
因此,这些天,上面使用prefix arg更可能被写入(并且被更好地写)为:
from myapp import views
urlpatterns = patterns('',
url('^$', views.myview),
url('^other/$', views.otherview),
)
因此,patterns()没有什么用处,并且是教新用户时的负担(回答新手的问题“为什么我需要这个空字符串作为patterns()由于这些原因,我们正在弃用它。更新代码非常简单,只要确保urlpatterns是django.conf.urls.url()实例的列表即可。例如:
from django.conf.urls import url
from myapp import views
urlpatterns = [
url('^$', views.myview),
url('^other/$', views.otherview),
]
内置模板上下文处理器已移至django.template.context_processors。
用于在测试中指定URLconf配置的属性SimpleTestCase.urls已被弃用,将在Django 2.0中删除。请改用@override_settings(ROOT_URLCONF=...)。
与上一个项目相关,django.conf.urls.i18n.i18n_patterns()的prefix参数已被弃用。只需传递django.conf.urls.url()实例的列表即可。
在for标记使用不正确的解压缩值计数将引发异常而不是在Django 2.0中静默失败。
通过Python路径反转URL是一个昂贵的操作,因为它导致反转路径被导入。此行为还导致了安全问题。请改用named URL patterns进行反转。
If you are using django.contrib.sitemaps, add the name argument to the url that references django.contrib.sitemaps.views.sitemap():
from django.contrib.sitemaps.views import sitemap
url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap')
以确保在通过Python路径反向时的兼容性在Django 2.0中被删除。
类似地,对于GIS Sitemap,请添加name='django.contrib.gis.sitemaps.views.kml'或name='django.contrib.gis.sitemaps.views.kmz'
The django.db.models.sql.aggregates and django.contrib.gis.db.models.sql.aggregates modules (both private API), have been deprecated as django.db.models.aggregates and django.contrib.gis.db.models.aggregates are now also responsible for SQL generation. 旧模块将在Django 2.0中删除。
如果您使用旧模块,请参阅Query Expressions,了解有关使用新的稳定API重写自定义聚合的说明。
django.db.models.sql.query.Query的以下方法和属性也已弃用,并且向后兼容性填充程序将在Django 2.0中删除:
管理命令现在使用argparse而不是optparse来解析传递给命令的命令行参数。这也意味着添加自定义参数到命令的方式已经改变:而不是扩展option_list类列表,您现在应该覆盖add_arguments()方法, argparse.add_argument()。有关详细信息,请参阅this example。
类NoArgsCommand现已弃用,将在Django 2.0中删除。使用BaseCommand,默认情况下不使用参数。
migrate管理命令的--list选项已弃用,将在Django 2.0中删除。请改用showmigrations。
ModelChoiceField和ModelMultipleChoiceField采用了未记录的未测试选项cache_choices。在同一个Form对象的多个呈现之间的缓存查询。此选项受到加速淘汰,并会在Django 1.9中移除。
该函数已被非正式地标记为“已弃用”一段时间。用django.template.Variable(path).resolve(context)替换resolve_variable(path, context)
它提供了lorem模板标记,现在包含在内置标记中。只需从INSTALLED_APPS和{% 载入 网页设计中移除'django.contrib.webdesign' %}。
它为1.0之前的代码提供向后兼容性,但其功能是多余的。请改用Field.error_messages['invalid']。
unordered_list模板过滤器的旧版本(pre-1.0),更严格和详细的输入格式已被弃用:
``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``
使用新的语法,这变成:
``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``
通过删除前导下划线将此方法重命名为has_changed()。旧的名称仍然会工作,直到Django 2.0。
django.utils.html.remove_tags()以及模板过滤器removetags已被弃用,因为它们无法保证安全输出。它们的存在可能导致它们在安全敏感的上下文中使用,在那里它们实际上是不安全的。
未使用和未记录的django.utils.html.strip_entities()函数已被弃用。
这是一个遗留的选项,不再需要。
django.db.models.fields.subclassing.SubfieldBase已被弃用,并会在Django 2.0中移除。历史上,它用于处理从数据库加载时需要进行类型转换的字段,但不用于.values()调用或聚合中。它已替换为from_db_value()。注意,新方法不像在SubfieldBase的情况那样调用to_python()方法。
django.utils.checksums模块已弃用,将在Django 2.0中删除。它提供的功能(使用Luhn算法验证校验和)是未记录的,不在Django中使用。模块已移至django-localflavor包(版本1.1+)。
InlineAdminForm上的original_content_type_id属性已弃用,将在Django 2.0中删除。历史上,它用于构建“在网站上查看”URL。现在可以使用表单的absolute_url属性访问此网址。
覆盖get_form()方法的FormMixin子类应确保为form_class参数提供默认值,因为它现在是可选的。
在Django 1.8中,get_template()的返回类型已改变:而不是django.template.Template,它返回一个Template类型取决于哪个后端加载它。
两个类都提供了一个render()方法,但是前者需要一个django.template.Context作为参数,而后者需要dict 。此更改通过Django模板的弃用路径强制实施。
由于使用示例更容易理解,upgrade guide显示了如何调整受影响的代码。
所有这一切也适用于select_template()。
SimpleTemplateResponse和TemplateResponse的一些方法接受django.template.Context和django.template.Template对象作为参数。他们现在应该分别接收dict和后端相关的模板对象。
这也适用于返回类型,如果你有子类模板响应类。
有关详细信息,请参阅template response API documentation。
以下函数将不再接受Django 2.0中的dictionary和context_instance参数:
请改用context参数。当dictionary作为位置参数传递时,这是最常见的习语,不需要更改。
如果您在context_instance中传递Context,请在context参数中传递dict。如果您传递RequestContext,请在request参数中单独传递请求。
以下函数将不再接受dirs参数以覆盖Django 2.0中的TEMPLATE_DIRS:
该参数不能在不同的模板加载器中一致工作,并且不适用于包含的模板。
django.template.loader.BaseLoader已重命名为django.template.loaders.base.Loader。如果您编写了继承BaseLoader的自定义模板加载器,则必须继承Loader。
已弃用专用API django.test.utils.TestTemplateLoader以支持django.template.loaders.locmem.Loader,并将在Django 1.9中移除。
Storage子类应向get_available_name()和/或save()添加max_length=None重写任一方法。支持不接受此参数的存储将在Django 2.0中删除。
在以前的Django版本中,各种内部ORM方法(大多是as_sql方法)接受了一个qn(“quote name”)参数,用于发送到数据库。在Django 1.8中,该参数已重命名为compiler,现在是一个完整的SQLCompiler实例。为了向后兼容,调用SQLCompiler实例执行与用于qn函数相同的名称引用。However, this backwards-compatibility shim is immediately deprecated: you should rename your qn arguments to compiler, and call compiler.quote_name_unless_alias(...) where you previously called qn(...).
在Django 1.9中,RedirectView.permanent属性的默认值将从True更改为False。
在Django 1.7中添加了django.contrib.auth.middleware.SessionAuthenticationMiddleware。在Django 1.7.2中,它的功能被移动到auth.get_user(),为了向后兼容,只有'django.contrib.auth.middleware.SessionAuthenticationMiddleware'出现在MIDDLEWARE_CLASSES中。
在Django 2.0中,无论是否启用SessionAuthenticationMiddleware(此时SessionAuthenticationMiddleware都没有意义),将启用会话验证。您可以在之前的某个时间将其添加到MIDDLEWARE_CLASSES,以便选择加入。请先阅读upgrade considerations。
django.contrib.sitemaps.FlatPageSitemap已移至django.contrib.flatpages.sitemaps.FlatPageSitemap。旧的导入位置已弃用,将在Django 1.9中删除。
ssi模板标记允许文件通过绝对路径包含在模板中。This is of limited use in most deployment situations, and the include tag often makes more sense. 此标记现已弃用,将在Django 2.0中移除。
在等号测试的模板标记中使用单个等号来标记未记录和未经测试的{% if %} 现已弃用,赞成==。
ModelFormMixin.success_url中的旧版%(<foo>)s语法已弃用,将在Django 2.0中删除。
The collect(), extent(), extent3d(), makeline(), and union() aggregate methods are deprecated and should be replaced by their function-based aggregate equivalents (Collect, Extent, Extent3D, MakeLine, and Union).
The signature of the allow_migrate() method of database routers has changed from allow_migrate(db, model) to allow_migrate(db, app_label, model_name=None, **hints).
When model_name is set, the value that was previously given through the model positional argument may now be found inside the hints dictionary under the key 'model'.
这些功能已过期,因此已在Django 1.8中移除(有关详情,请参阅deprecation timeline):
2015年5月13日