注意
致力于Malcolm Tredinnick
2013年3月17日,Django项目和自由软件社区失去了一个非常亲爱的朋友和开发人员。
马尔科姆是Django的一个长期贡献者,Django是一个模范社区成员,一个聪明的头脑和一个朋友。他对Django以及许多其他开源项目的贡献几乎不可能列举。许多核心Django团队的他们的第一个补丁审查他;他的导师丰富了我们。他的考虑,耐心和奉献将永远是我们的灵感。
这个版本的Django是Malcolm的。
- Django开发人员
2013年11月6日
欢迎来到Django 1.6!
这些发行说明涵盖新功能以及一些向后不兼容更改,您需要知道从Django 1.5或更早版本升级时。我们还删除了一些功能,详情请参阅our deprecation plan,我们已开始针对某些功能的弃用流程。
Django 1.6,像Django 1.5,需要Python 2.6.5或更高版本。Python 3也正式支持。我们强烈推荐每个支持的Python系列(2.6.X,2.7.X,3.2.X和3.3.X)的最新版本。
Django 1.6将是最终发布系列支持Python 2.6;从Django 1.7开始,最低支持的Python版本将是2.7。
不支持Python 3.4,但将在Django 1.7中添加支持。
startproject和startapp使用的默认模板已经过简化和现代化。默认情况下,在新项目中启用admin; sites框架不再是。clickjacking prevention现在启用,数据库默认为SQLite。
如果默认模板不符合您的品味,可以使用custom project and app templates。
Django的事务管理被大修。默认情况下,数据库级自动提交已打开。这使得事务处理更加明确,并且应该提高性能。现有的API已被弃用,并引入了新的API,如transaction management docs中所述。
Django现在支持为多个请求重用相同的数据库连接。这避免了在每个请求开始时重新建立连接的开销。为了向后兼容性,默认情况下禁用此功能。有关详细信息,请参见Persistent connections。
Django 1.6附带了一个新的测试运行器,允许更多的测试位置灵活性。上一个转轮(django.test.simple.DjangoTestSuiteRunner)仅在Python包的models.py和tests.py模块中发现测试在INSTALLED_APPS中。
新转轮(django.test.runner.DiscoverRunner)使用unittest2(Python 2.7中的unittest版本)中内置的测试发现功能+标准库,并与Django捆绑在一起)。使用测试发现,测试可以位于名称与模式test*.py匹配的任何模块中。
此外,提供给./ manage.py 测试以提名要运行的特定测试的测试标签现在必须是完整的Python虚线路径目录路径),而不是applabel.TestCase.test_method_name伪路径。这允许运行位于代码库任何位置的测试,而不只是在INSTALLED_APPS中。有关详细信息,请参阅Testing in Django。
此更改向后不兼容;请参阅backwards-incompatibility notes。
在Django 1.4中引入的对time zones的支持在QuerySet.dates()中无法正常工作:聚合始终以UTC执行。这个限制在Django 1.6中解除。使用QuerySet.datetimes()在DateTimeField上执行时区感知聚合。
Django 1.6在SQLite中添加了对保存点的支持,有一些limitations。
新的django.db.models.BinaryField模型字段允许在数据库中存储原始二进制数据。
GeoDjango现在为其地理专业字段提供form fields and widgets。它们是基于OpenLayers的,默认情况下,但他们可以定制使用任何其他JS框架。
添加了check管理命令,使您能够验证当前配置(当前定位于设置)是否与当前版本的Django兼容。
如果实例具有主键值,则Model.save()方法现在将直接尝试UPDATE。以前执行SELECT以确定是否需要UPDATE或INSERT。新算法仅需要一个查询来更新现有行,而旧算法需要两个查询。有关详细信息,请参阅Model.save()。
在少数情况下,数据库在执行UPDATE时不会报告找到匹配的行。一个例子是PostgreSQL ON UPDATE触发器,返回NULL。在这种情况下,可以设置django.db.models.Options.select_on_save标志,以强制保存使用旧算法。
警告
除了本节中概述的更改外,请务必查看已删除的任何功能的deprecation plan。如果您没有在指定功能的弃用时间轴内更新代码,则其移除可能会显示为向后不兼容的更改。
默认情况下,Django 1.6中启用数据库级自动提交。虽然这不改变Django的事务管理的一般精神,但有一些向后兼容性。
事务管理中的更改可能会导致创建,释放或回滚保存点的其他语句。这是更可能发生与SQLite,因为它不支持保存点,直到此版本。
如果使用assertNumQueries()的测试失败,因为查询数量大于预期,请检查额外的查询是否与保存点相关,并相应地调整预期的查询数量。
在以前的版本中,数据库级自动提交只是PostgreSQL的一个选项,默认情况下它被禁用。此选项现在被忽略,可以删除。
为了与Python的unittest模块保持更大的一致性,新的测试运行器(django.test.runner.DiscoverRunner)不会自动支持上一个运行器支持的一些类型的测试:
Django从Python标准库(在django.test._doctest)中捆绑了doctest模块的修改版本,并包含一些额外的doctest实用程序。这些实用程序已弃用,将在Django 1.8中删除; doctest套件应该更新为使用标准库的doctest模块(或转换为与unittest兼容的测试)。
如果您希望延迟更新测试套件,可以将TEST_RUNNER设置设置为django.test.simple.DjangoTestSuiteRunner,以完全恢复旧的测试行为。DjangoTestSuiteRunner is deprecated but will not be removed from Django until version 1.8.
这是为开发人员在GeoDjango应用程序本身和上面的项目相关的测试赛跑者的变化:
django.contrib.gis.tests.GeoDjangoTestSuiteRunner测试运行器已删除,并且不再支持独立的GeoDjango测试执行设置。要运行GeoDjango测试,只需使用新的DiscoverRunner并指定django.contrib.gis应用。
新的测试运行器的引入也略微改变了导入测试模型的方式。因此,任何覆盖AUTH_USER_MODEL以使用Django的测试用户模型(CustomUser和ExtensionUser)测试行为的测试现在必须明确导入测试模块中的用户模型:
from django.contrib.auth.tests.custom_user import CustomUser
@override_settings(AUTH_USER_MODEL='auth.CustomUser')
class CustomUserFeatureTests(TestCase):
def test_something(self):
# Test code here ...
此导入强制要注册自定义用户模型。如果没有此导入,测试将无法在自定义用户模型中进行交换,您将收到错误报告:
ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.CustomUser' that has not been installed
对于day,month和week_day个查询,当USE_TZ为True这些查找以前在UTC中执行,而不考虑当前时区。
这需要数据库中的time zone definitions in the database。如果您使用SQLite,您必须安装pytz。如果您使用的是MySQL,则必须安装pytz,并使用mysql_tzinfo_to_sql加载时区表。
当在Django 1.4中添加的time zone support处于活动状态时,QuerySet.dates()查找返回意外结果,因为聚合是以UTC执行的。为了解决这个问题,Django 1.6引入了一个新的API,QuerySet.datetimes()。这需要在代码中进行一些更改。
QuerySet.dates()现在返回date的列表。它用于返回datetime的列表。
QuerySet.dates() raises an error if it’s used on DateTimeField when time zone support is active. 请改用QuerySet.datetimes()。
管理员的date_hierarchy功能现在在DateTimeField上使用时,依靠QuerySet.datetimes()。
这在USE_TZ为True时需要数据库中的时区定义。Learn more。
出于同样的原因,在基于日期的通用视图的上下文中访问date_list时,当视图基于DateTimeField和USE_TZ为True。Learn more。
Django 1.6在DateTimeField上引入hour,minute和second如果您有名为hour,minute或second的模型字段,新的查找将与您的字段名称冲突。如果这是一个问题,请附加显式的exact查询。
当BooleanField没有显式的default时,隐式默认值为None。在以前的Django版本中,它是False,但是没有准确表示缺少值。
依赖于默认值False的代码在将新模型实例保存到数据库时可能会引发异常,因为None对于BooleanField。您应该在字段定义中指定default=False,或者在保存对象之前,确保该字段设置为True或False。
使用makemessages命令从模板中提取可翻译文字现在可以正确检测i18n结构位于{# / #}在同一行。例如。:
{##}{% trans "This literal was incorrectly ignored. Not anymore" %}
Comments for translators in templates specified using {# / #} need to be at the end of a line. 如果不是,则忽略注释,makemessages将生成警告。例如:
{##}{% trans "Translate me" %}
{{ title }}{##}
<h1>{% trans "Welcome" %}</h1>
当翻转网址时,Django在网址格式中插入参数之前未将urlquote()应用于参数。这个bug在Django 1.6中修复。如果您通过在传递参数到reverse()之前应用网址引用来解决此错误,则可能会导致双引号。如果发生这种情况,只需从代码中删除网址引用。您还必须用其编码版本替换assertRedirects()中使用的网址中的特殊字符。
评论应用程序现在使用GenericIPAddressField存储评论者的IP地址,以支持从IPv6地址提交的评论。到现在为止,它将它们存储在IPAddressField中,这只意味着支持IPv4。当保存从IPv6地址发出的注释时,该地址将在MySQL数据库上被静默截断,并在Oracle上引发异常。您将需要更改数据库中的列类型以受益于此更改。
对于MySQL,在项目的数据库上执行此查询:
ALTER TABLE django_comments MODIFY ip_address VARCHAR(39);
对于Oracle,请执行以下查询:
ALTER TABLE DJANGO_COMMENTS MODIFY (ip_address VARCHAR2(39));
如果不应用此更改,行为不变:在MySQL上,IPv6地址将被静默截断;在Oracle上,会生成异常。SQLite或PostgreSQL数据库不需要更改数据库。
当通过cursor.execute方法运行原始SQL查询时,关于查询中的两倍百分比文本(%)的规则已经统一。过去的行为取决于数据库后端。现在,在所有后端,如果您还提供替换参数,则只需要加倍文字百分比字符。例如:
# No parameters, no percent doubling
cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")
# Parameters passed, non-placeholders have to be doubled
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' and id = %s", [self.id])
SQLite用户需要检查和更新此类查询。
与ManyToManyField对应的模型表单字段的HTML呈现用于获取硬编码的句子:
Hold down “Control”, or “Command” on a Mac, to select more than one.
(or its translation to the active locale) imposed as the help legend shown along them if neither model nor form help_text attributes were specified by the user (or this string was appended to any help_text that was provided).
因为这发生在模型层,所以没有办法防止文本在不适用的情况下出现,例如实现不涉及键盘和/或鼠标的用户交互的表单域。
从Django 1.6开始,作为一种特殊的临时向后兼容性规定,添加“Hold down ...”句子的逻辑已经移动到模型表单字段层,并被修改为仅当相关的小部件SelectMultiple或选择的子类。
如果您为ManyToManyField模型字段使用自定义模型表单字段和/或窗口小部件,其UI依赖于自动提供的上述硬编码语句,则该更改可能以向后不兼容的方式影响您。这些表单字段实现需要通过提供自己的help_text属性处理来适应新的场景。
使用Django model form设施以及Django内置形式fields和widgets的应用程序不受影响,但需要了解所描述的内容在Munging of help text of model form fields for ManyToManyField fields下面。
QuerySet迭代已更改为立即将所有获取的行转换为Model对象。在Django 1.5和更早版本中,获取的行转换为大小为100的Model对象。
现有代码将工作,但在某些用例中,转换为对象的行数可能会发生变化。这样的用法包括部分循环查询集或任何使用__bool__或__contains__。
值得注意的是,大多数数据库后端已经在1.5中一次性提取所有行。
仍然可以使用iterator()方法将提取的行延迟转换为Model对象。
这与Form.as_p和Form.as_ul渲染标签的方法是一致的。
如果您在模板中手动呈现label_tag:
{{ form.my_field.label_tag }}: {{ form.my_field }}
您需要删除冒号(或任何其他可能使用的分隔符),以避免在升级到Django 1.6时重复它。除了冒号将出现在<label>元素中,Django 1.6中的以下模板将与Django 1.5中的上述模板完全相同。
{{ form.my_field.label_tag }} {{ form.my_field }}
将呈现如下:
<label for="id_my_field">My Field:</label> <input id="id_my_field" type="text" name="my_field" />
如果要保留当前没有label_suffix的label_tag的行为,请实例化形式label_suffix=''。您还可以使用label_tag()上的新label_suffix参数,在每个字段基础上自定义label_suffix。
为了实现保留和恢复列表视图过滤器,管理视图现在传递_changelist_filters GET参数。如果您有自定义管理模板,或者您的测试依赖于之前的网址,请记住这一变化。如果要恢复原始行为,可以将preserve_filters属性设置为False。
过去版本的Django在密码重置视图和URL(django.contrib.auth.views.password_reset_confirm())中使用User主键的第36个编码。如果用户主键是整数,则Base 36编码就足够了,但是,随着在Django 1.5中引入自定义用户模型,该假设可能不再是真的。
django.contrib.auth.views.password_reset_confirm()已修改为采用uidb64参数,而不是uidb36。如果您要撤消此视图,例如在自定义password_reset_email.html模板中,请务必更新您的代码。
django.contrib.auth.views.password_reset_confirm()的临时垫片将允许在Django 1.6之前生成的密码重置链接继续工作,以添加向后兼容性;这将在Django 1.7中删除。因此,只要您的网站在超过PASSWORD_RESET_TIMEOUT_DAYS的情况下运行Django 1.6,此更改就不会生效。如果没有(例如,如果您直接从Django 1.5升级到Django 1.7),则在升级到Django 1.7或更高版本之前生成的任何密码重置链接在升级后将不起作用。
此外,如果您有任何自定义密码重置网址,则需要更新它们,方法是将uidb36替换为uidb64,然后使用斜杠替换该模式后面的破折号。还可将_\-添加到可能与uidb64模式匹配的字符列表中。
例如:
url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm',
name='password_reset_confirm'),
变为:
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm',
name='password_reset_confirm'),
您还可以添加垫片以支持旧样式重置链接。使用上述示例,您可以使用django.contrib.auth.views.password_reset_confirm_uidb36替换django.contrib.auth.views.password_reset_confirm来修改现有的网址,同时删除name参数,因此它与新网址不冲突:
url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm_uidb36'),
您可以在使用Django 1.6为PASSWORD_RESET_TIMEOUT_DAYS部署应用程式后,移除此网址格式。
历史上,django.contrib.sessions使用pickle将会话数据序列化,然后将其存储在后端。如果您使用的是signed cookie session backend,而且SECRET_KEY已被攻击者所知(Django没有固有的漏洞会导致漏洞)攻击者可以在他的会话中插入一个字符串,当它取消绑定时,在服务器上执行任意代码。这样做的技术是简单和容易在互联网上。虽然cookie会话存储签名cookie存储的数据,以防止篡改,SECRET_KEY泄漏立即升级到远程代码执行漏洞。
这种攻击可以通过使用JSON而不是pickle来序列化会话数据来缓解。为了方便起见,Django 1.5.3引入了一个新的设置,SESSION_SERIALIZER来定制会话序列化格式。为了向后兼容性,此设置默认使用Django 1.5.3中的pickle,但我们在1.6中将默认值更改为JSON。如果您升级并从pickle切换到JSON,在升级之前创建的会话将丢失。虽然JSON序列化不支持像pickle这样的所有Python对象,但我们强烈建议使用JSON序列化会话。在检查代码以确定JSON序列化是否适用于您的应用程序时,请注意以下事项:
有关详细信息,请参阅Session serialization文档。
Django 1.6包含对ORM的许多更改。这些变化主要分为三类:
这些更改可能会导致一些兼容性问题。例如,一些查询现在将生成不同的表别名。这可能会影响QuerySet.extra()。此外,一些查询现在将产生不同的结果。示例是exclude(condition)其中条件是复杂的(引用Q objects内的多联接)。在许多情况下,受影响的查询在Django 1.5中没有产生正确的结果,但现在做了。不幸的是,有些情况下会产生不同的结果,但是Django 1.5和1.6都不会产生正确的结果。
最后,对ORM内部API进行了许多更改。
django.db.models.query.EmptyQuerySet不能再被实例化 - 它只能用作检查none()是否被调用的标记类: isinstance(qs.none(), EmptyQuerySet)
If your CSS/JavaScript code used to access HTML input widgets by type, you should review it as type='text' widgets might be now output as type='email', type='url' or type='number' depending on their corresponding field type.
Form field’s error_messages that contain a placeholder should now always use a named placeholder ("Value '%(value)s' is too big" instead of "Value '%s' is too big"). 有关占位符名称的详细信息,请参阅相应的字段文档。1.6中的更改特别影响DecimalField和ModelMultipleChoiceField。
Some error_messages for IntegerField, EmailField, IPAddressField, GenericIPAddressField, and SlugField have been suppressed because they duplicated error messages already provided by validators tied to the fields.
由于表单验证工作流程中的更改,TypedChoiceField coerce方法应始终返回choices字段属性中显示的值。这个限制应该在Django 1.7中再次提升。
缓存后端中处理超时的方式已发生变化。在timeout=None中显式传递不再导致使用默认超时。它现在将设置非到期超时。将0传递到memcache后端不再使用默认超时,现在将立即设置并过期该值。
用于设置自定义HTTP标头以供调试的django.contrib.flatpages应用程序。此功能未记录,并使缓存无效,因此已被删除,以及其通用实现,以前在django.core.xheaders中可用。
XViewMiddleware已从django.middleware.doc移至django.contrib.admindocs.middleware,因为它是admindocs的实施细节,经过验证不可重复使用。
GenericIPAddressField现在只允许blank值,如果null值也允许。创建GenericIPAddressField其中blank但允许null不会触发模型验证错误,因为blank存储为null。以前,在不允许null的字段中存储blank值会在运行时导致数据库异常。
如果在渲染模板时从方法引发了NoReverseMatch异常,则不会将其置于静默状态。例如,{{ obj.view_href }}会导致模板渲染失败,如果view_href()提高NoReverseMatch。{% url %}标记没有变化,导致模板呈现失败, NoReverseMatch。
django.test.Client.logout()现在调用django.contrib.auth.logout(),它将发送user_logged_out()信号。
Authentication views现在按名称颠倒,而不是它们在django.contrib.auth.views中的位置。If you are using the views without a name, you should update your urlpatterns to use url() with the name parameter. 例如:
(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete')
变为:
url(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete', name='password_reset_complete')
RedirectView现在有一个pattern_name属性,它允许它通过反转URL来选择目标。
在Django 1.4和1.5中,一个空白字符串被无意识地认为不是有效的密码。这意味着set_password()将以set_unusable_password()的方式将空白密码保存为不可用的密码,因此check_password()总是返回False用于空白密码。此版本中已更正:空密码现在有效。
管理员changelist_view先前接受了一个pop GET参数,表示它将显示在弹出式窗口中。此参数已重命名为_popup,以与其余管理视图一致。如果自定义模板使用之前的参数名称,则应更新自定义模板。
validate_email()现在接受以localhost作为域的电子邮件地址。
--keep-pot选项已添加到makemessages,以防止django在创建.po文件之前删除其生成的临时.pot文件。
未记录的django.core.servers.basehttp.WSGIServerException已删除。使用标准库提供的socket.error。这个更改也在Django 1.5.5中发布。
django.views.generic.base.RedirectView.get_redirect_url()的签名已更改,现在也接受位置参数(* args, * * kwargs)。任何未命名捕获的组现在将传递到get_redirect_url(),如果不更新自定义方法的签名,则可能会导致TypeError。
事务管理在Django 1.6中彻底翻修,目前的API已弃用:
Django的注释框架已被弃用,不再支持。它将在Django 1.6和1.7中可用,并在Django 1.8中删除。大多数用户将更好地服务于自定义解决方案或托管产品,如Disqus。
以前称为django.contrib.comments的代码仍然在外部存储库中可用。
上游支持期的结束在2011年12月达到了PostgreSQL 8.2,2013年2月达到了8.3。因此,Django 1.6将8.4设置为它正式支持的最小PostgreSQL版本。
强烈建议您使用最新版本的PostgreSQL,因为性能改进,并利用PostgreSQL 9.x中提供的本地流复制。
模板系统通常转义所有变量以避免XSS攻击。然而,由于历史的意外,cycle和firstof
Django 1.6启动一个进程来纠正这种不一致。future模板库提供了自动转义其输入的cycle和firstof的替代实现。如果您使用这些代码,建议您在模板顶部添加以下行,以启用新的行为:
{% load cycle from future %}
要么:
{% load firstof from future %}
实施旧行为的标签已被弃用,在Django 1.8中,旧行为将替换为新行为。为了确保与Django的未来版本兼容,应修改现有模板以使用future版本。
如有必要,您可以暂时使用mark_safe()或{% autoescape off %}。
CacheMiddleware和UpdateCacheMiddleware用于提供一种缓存请求的方法,前提是这些请求不是由登录用户发出的。这种机制很大程度上无效,因为中间件正确地考虑了Vary: Cookie HTTP头,并且这个头被设置在各种场合,如:
这使得高速缓存基于每个会话有效地工作,而不管CACHE_MIDDLEWARE_ANONYMOUS_ONLY设置。
CommonMiddleware用于在SEND_BROKEN_LINK_EMAILS设置为True时通过电子邮件提供中断链接的基本报告。
由于CommonMiddleware和LocaleMiddleware之间的棘手顺序问题,此功能被拆分为一个新的中间件:BrokenLinkEmailsMiddleware。
如果您要使用此功能,请将'django.middleware.common.BrokenLinkEmailsMiddleware'添加到您的MIDDLEWARE_CLASSES设置中,并从中删除SEND_BROKEN_LINK_EMAILS您的设置。
如果您定义了自己的窗体小部件并在窗口小部件上定义了_has_changed方法,那么现在应该在窗体字段上定义此方法。
Model._meta.module_name已重命名为model_name。尽管是一个私有API,它将通过一个常规的弃用路径。
Model._meta.get_(add|change|delete)_permission方法已弃用。即使它们不是公共API的一部分,他们也将通过常规的弃用路径。You can replace them with django.contrib.auth.get_permission_codename('action', Model._meta) where 'action' is 'add', 'change', or 'delete'.
返回QuerySet(例如Manager.get_query_set或ModelAdmin.queryset的方法)已重命名为get_queryset。
如果您正在编写实现了例如Manager.get_query_set方法的库,并且需要支持旧的Django版本,则应重命名该方法并有条件地添加具有旧名称的别名:
class CustomManager(models.Manager):
def get_queryset(self):
pass # ...
if django.VERSION < (1, 6):
get_query_set = get_queryset
# For Django >= 1.6, models.Manager provides a get_query_set fallback
# that emits a warning when used.
如果您正在编写需要调用get_queryset方法并且必须支持旧Django版本的库,您应该写:
get_queryset = (some_manager.get_query_set
if hasattr(some_manager, 'get_query_set')
else some_manager.get_queryset)
return get_queryset() # etc
在自定义管理器实现自己的get_queryset方法并调用该方法,并需要使用旧的Django版本和尚未更新的库的一般情况下,定义a get_queryset_compat方法,并在内部使用到您的经理:
class YourCustomManager(models.Manager):
def get_queryset(self):
return YourCustomQuerySet() # for example
get_query_set = get_queryset
def active(self): # for example
return self.get_queryset_compat().filter(active=True)
def get_queryset_compat(self):
get_queryset = (self.get_query_set
if hasattr(self, 'get_query_set')
else self.get_queryset)
return get_queryset()
这有助于最小化所需的更改,但也可以在子类(例如来自Django 1.5的RelatedManagers)中正确工作,这可能会覆盖get_query_set或get_queryset。
在1.0版本后不久,shortcut视图从django.views.defaults移动到django.contrib.contenttypes.views,但旧位置从来没有被淘汰。这个疏忽在Django 1.6中得到纠正,您现在应该使用新位置。
URLconf django.conf.urls.shortcut也已弃用。如果您将其包含在URLconf中,只需替换:
(r'^prefix/', include('django.conf.urls.shortcut')),
具有:
(r'^prefix/(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'django.contrib.contenttypes.views.shortcut'),
以前,如果您想要ModelForm使用模型中的所有字段,则可以忽略Meta.fields属性,并使用所有字段。
这可能导致安全问题,其中字段被添加到模型中,并且无意地,最终用户自动地可编辑。在某些情况下,特别是对于布尔字段,这个问题可能是完全不可见的。这是批量指派漏洞的一种形式。
因此,此行为已被弃用,并且强烈建议您不要使用Meta.exclude选项。而是,应该在fields属性中明确列出要包含在表单中的所有字段。
如果此安全问题确实不适用于您的情况,则有一个快捷方式可显式指示应使用所有字段 - 对于fields属性使用特殊值"__all__":
class MyModelForm(ModelForm):
class Meta:
fields = "__all__"
model = MyModel
如果您有需要在管理中使用的自定义ModelForms,则还有另一个选项。管理员有自己的方法来定义字段(fieldsets等)。),因此向ModelForm添加字段列表是多余的。而只需省略ModelForm的Meta内部类,或省略Meta.model属性。由于ModelAdmin子类知道它所使用的模型,因此它可以添加必要的属性来派生一个运行的ModelForm。此行为也适用于早期的Django版本。
通用视图CreateView和UpdateView以及从ModelFormMixin派生的任何内容都容易受到上述部分所述的安全问题的影响,因为他们可以自动创建使用模型的所有字段的ModelForm。
For this reason, if you use these views for editing models, you must also supply the fields attribute (new in Django 1.6), which is a list of model fields and works in the same way as the ModelForm Meta.fields attribute. 或者,您可以将form_class属性设置为明确定义要使用的字段的ModelForm。定义要与模型一起使用但没有显式字段列表的UpdateView或CreateView子类已弃用。
All special handling of the help_text attribute of ManyToManyField model fields performed by standard model or model form fields as described in Help text of model form fields for ManyToManyField fields above is deprecated and will be removed in Django 1.8.
这些字段的帮助文本将需要由应用程序,自定义表单字段或窗口小部件处理,就像其余模型字段类型一样。
2015年5月13日