mirror of
https://github.com/django/django.git
synced 2024-12-23 09:36:06 +00:00
718 lines
28 KiB
Plaintext
718 lines
28 KiB
Plaintext
============================================
|
|
Django 1.8 release notes - UNDER DEVELOPMENT
|
|
============================================
|
|
|
|
Welcome to Django 1.8!
|
|
|
|
These release notes cover the `new features`_, as well as some `backwards
|
|
incompatible changes`_ you'll want to be aware of when upgrading from Django
|
|
1.6 or older versions. We've also dropped some features, which are detailed in
|
|
:ref:`our deprecation plan <deprecation-removed-in-1.8>`, and we've `begun the
|
|
deprecation process for some features`_.
|
|
|
|
.. _`new features`: `What's new in Django 1.8`_
|
|
.. _`backwards incompatible changes`: `Backwards incompatible changes in 1.8`_
|
|
.. _`begun the deprecation process for some features`: `Features deprecated in 1.8`_
|
|
|
|
Python compatibility
|
|
====================
|
|
|
|
Like Django 1.7, Django 1.8 requires Python 2.7 or above, though we
|
|
**highly recommend** the latest minor release.
|
|
|
|
What's new in Django 1.8
|
|
========================
|
|
|
|
...
|
|
|
|
Minor features
|
|
~~~~~~~~~~~~~~
|
|
|
|
:mod:`django.contrib.admin`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* :class:`~django.contrib.admin.ModelAdmin` now has a
|
|
:meth:`~django.contrib.admin.ModelAdmin.has_module_permission`
|
|
method to allow limiting access to the module on the admin index page.
|
|
|
|
* :class:`~django.contrib.admin.InlineModelAdmin` now has an attribute
|
|
:attr:`~django.contrib.admin.InlineModelAdmin.show_change_link` that
|
|
supports showing a link to an inline object's change form.
|
|
|
|
* Use the new ``django.contrib.admin.RelatedOnlyFieldListFilter`` in
|
|
:attr:`ModelAdmin.list_filter <django.contrib.admin.ModelAdmin.list_filter>`
|
|
to limit the ``list_filter`` choices to foreign objects which are attached to
|
|
those from the ``ModelAdmin``.
|
|
|
|
* The :meth:`ModelAdmin.delete_view()
|
|
<django.contrib.admin.ModelAdmin.delete_view>` displays a summary of objects
|
|
to be deleted on the deletion confirmation page.
|
|
|
|
* The jQuery library embedded in the admin has been upgraded to version 1.11.1.
|
|
|
|
:mod:`django.contrib.auth`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* Authorization backends can now raise
|
|
:class:`~django.core.exceptions.PermissionDenied` in
|
|
:meth:`~django.contrib.auth.models.User.has_perm`
|
|
and :meth:`~django.contrib.auth.models.User.has_module_perms`
|
|
to short-circuit permission checking.
|
|
* :class:`~django.contrib.auth.forms.PasswordResetForm` now
|
|
has a method :meth:`~django.contrib.auth.forms.PasswordResetForm.send_email`
|
|
that can be overridden to customize the mail to be sent.
|
|
* The ``max_length`` of :attr:`Permission.name
|
|
<django.contrib.auth.models.Permission.name>` has been increased from 50 to
|
|
255 characters. Please run the database migration.
|
|
* :attr:`~django.contrib.auth.models.CustomUser.USERNAME_FIELD` and
|
|
:attr:`~django.contrib.auth.models.CustomUser.REQUIRED_FIELDS` now supports
|
|
:class:`~django.db.models.ForeignKey`\s.
|
|
|
|
:mod:`django.contrib.formtools`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* A :doc:`form wizard </ref/contrib/formtools/form-wizard>` using the
|
|
:class:`~django.contrib.formtools.wizard.views.CookieWizardView` will now ignore
|
|
an invalid cookie, and the wizard will restart from the first step. An invalid
|
|
cookie can occur in cases of intentional manipulation, but also after a secret
|
|
key change. Previously, this would raise ``WizardViewCookieModified``, a
|
|
``SuspiciousOperation``, causing an exception for any user with an invalid cookie
|
|
upon every request to the wizard, until the cookie is removed.
|
|
|
|
:mod:`django.contrib.gis`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* Compatibility shims for ``SpatialRefSys`` and ``GeometryColumns`` changed in
|
|
Django 1.2 have been removed.
|
|
|
|
* The Spatialite backend now supports ``Collect`` and ``Extent`` aggregates
|
|
when the database version is 3.0 or later.
|
|
|
|
:mod:`django.contrib.messages`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* ...
|
|
|
|
:mod:`django.contrib.redirects`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* ...
|
|
|
|
:mod:`django.contrib.sessions`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* Session cookie is now deleted after
|
|
:meth:`~django.contrib.sessions.backends.base.SessionBase.flush()` is called.
|
|
|
|
:mod:`django.contrib.sitemaps`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* The new :attr:`Sitemap.i18n <django.contrib.sitemaps.Sitemap.i18n>` attribute
|
|
allows you to generate a sitemap based on the :setting:`LANGUAGES` setting.
|
|
|
|
:mod:`django.contrib.sites`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* ...
|
|
|
|
:mod:`django.contrib.staticfiles`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* ...
|
|
|
|
:mod:`django.contrib.syndication`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* ...
|
|
|
|
Cache
|
|
^^^^^
|
|
|
|
* ...
|
|
|
|
Email
|
|
^^^^^
|
|
|
|
* :ref:`Email backends <topic-email-backends>` now support the context manager
|
|
protocol for opening and closing connections.
|
|
|
|
File Storage
|
|
^^^^^^^^^^^^
|
|
|
|
* ...
|
|
|
|
File Uploads
|
|
^^^^^^^^^^^^
|
|
|
|
* ...
|
|
|
|
Forms
|
|
^^^^^
|
|
|
|
* Form widgets now render attributes with a value of ``True`` or ``False``
|
|
as HTML5 boolean attributes.
|
|
|
|
* The new :meth:`~django.forms.Form.has_error()` method allows checking
|
|
if a specific error has happened.
|
|
|
|
* If :attr:`~django.forms.Form.required_css_class` is defined on a form, then
|
|
the ``<label>`` tags for required fields will have this class present in its
|
|
attributes.
|
|
|
|
* The rendering of non-field errors in unordered lists (``<ul>``) now includes
|
|
``nonfield`` in its list of classes to distinguish them from field-specific
|
|
errors.
|
|
|
|
* :class:`~django.forms.Field` now accepts a
|
|
:attr:`~django.forms.Field.label_suffix` argument, which will override the
|
|
form's :attr:`~django.forms.Form.label_suffix`. This enables customizing the
|
|
suffix on a per-field basis — previously it wasn't possible to override
|
|
a form's :attr:`~django.forms.Form.label_suffix` while using shortcuts such
|
|
as ``{{ form.as_p }}`` in templates.
|
|
|
|
* :class:`~django.forms.extras.widgets.SelectDateWidget` now accepts an
|
|
:attr:`~django.forms.extras.widgets.SelectDateWidget.empty_label` argument, which will
|
|
override the top list choice label when :class:`~django.forms.DateField` is not required.
|
|
|
|
* After an :class:`~django.forms.ImageField` has been cleaned and validated, the
|
|
``UploadedFile`` object will have an additional ``image`` attribute containing
|
|
the Pillow ``Image`` instance used to check if the file was a valid image. It
|
|
will also update ``UploadedFile.content_type`` with the image's content type
|
|
as determined by Pillow.
|
|
|
|
Generic Views
|
|
^^^^^^^^^^^^^
|
|
|
|
* Generic views that use :class:`~django.views.generic.list.MultipleObjectMixin`
|
|
may now specify the ordering applied to the
|
|
:attr:`~django.views.generic.list.MultipleObjectMixin.queryset` by setting
|
|
:attr:`~django.views.generic.list.MultipleObjectMixin.ordering` or overriding
|
|
:meth:`~django.views.generic.list.MultipleObjectMixin.get_ordering()`.
|
|
|
|
Internationalization
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* :setting:`FORMAT_MODULE_PATH` can now be a list of strings representing
|
|
module paths. This allows importing several format modules from different
|
|
reusable apps. It also allows overriding those custom formats in your main
|
|
Django project.
|
|
|
|
Management Commands
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
* :djadmin:`dumpdata` now has the option :djadminopt:`--output` which allows
|
|
specifying the file to which the serialized data is written.
|
|
|
|
* :djadmin:`makemessages` and :djadmin:`compilemessages` now have the option
|
|
:djadminopt:`--exclude` which allows exclusion of specific locales from
|
|
processing.
|
|
|
|
* The :djadminopt:`--ignorenonexistent` option of the :djadmin:`loaddata`
|
|
management command now ignores data for models that no longer exist.
|
|
|
|
* :djadmin:`runserver` now uses daemon threads for faster reloading.
|
|
|
|
* :djadmin:`inspectdb` now outputs ``Meta.unique_together``.
|
|
|
|
* When calling management commands from code through :ref:`call_command
|
|
<call-command>` and passing options, the option name can match the command
|
|
line option name (without the initial dashes) or the final option destination
|
|
variable name, but in either case, the resulting option received by the
|
|
command is now always the ``dest`` name specified in the command option
|
|
definition (as long as the command uses the new :py:mod:`argparse` module).
|
|
|
|
* The :djadmin:`dbshell` command now supports MySQL's optional SSL certificate
|
|
authority setting (``--ssl-ca``).
|
|
|
|
Models
|
|
^^^^^^
|
|
|
|
* Django now logs at most 9000 queries in ``connections.queries``, in order
|
|
to prevent excessive memory usage in long-running processes in debug mode.
|
|
|
|
* There is now a model ``Meta`` option to define a
|
|
:attr:`default related name <django.db.models.Options.default_related_name>`
|
|
for all relational fields of a model.
|
|
|
|
* Pickling models and querysets across different versions of Django isn't
|
|
officially supported (it may work, but there's no guarantee). An extra
|
|
variable that specifies the current Django version is now added to the
|
|
pickled state of models and querysets, and Django raises a ``RuntimeWarning``
|
|
when these objects are unpickled in a different version than the one in
|
|
which they were pickled.
|
|
|
|
* Added :meth:`Model.from_db() <django.db.models.Model.from_db()>` which
|
|
Django uses whenever objects are loaded using the ORM. The method allows
|
|
customizing model loading behavior.
|
|
|
|
Signals
|
|
^^^^^^^
|
|
|
|
* Exceptions from the ``(receiver, exception)`` tuples returned by
|
|
:meth:`Signal.send_robust() <django.dispatch.Signal.send_robust>` now have
|
|
their traceback attached as a ``__traceback__`` attribute.
|
|
|
|
Templates
|
|
^^^^^^^^^
|
|
|
|
* :tfilter:`urlize` now supports domain-only links that include characters after
|
|
the top-level domain (e.g. ``djangoproject.com/`` and
|
|
``djangoproject.com/download/``).
|
|
|
|
Requests and Responses
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* ``WSGIRequest`` now respects paths starting with ``//``.
|
|
|
|
* The :meth:`HttpRequest.build_absolute_uri()
|
|
<django.http.HttpRequest.build_absolute_uri>` method now handles paths
|
|
starting with ``//`` correctly.
|
|
|
|
* If :setting:`DEBUG` is ``True`` and a request raises a
|
|
:exc:`~django.core.exceptions.SuspiciousOperation`, the response will be
|
|
rendered with a detailed error page.
|
|
|
|
* The ``query_string`` argument of :class:`~django.http.QueryDict` is now
|
|
optional, defaulting to ``None``, so a blank ``QueryDict`` can now be
|
|
instantiated with ``QueryDict()`` instead of ``QueryDict(None)`` or
|
|
``QueryDict('')``.
|
|
|
|
* The ``GET`` and ``POST`` attributes of an :class:`~django.http.HttpRequest`
|
|
object are now :class:`~django.http.QueryDict`\s rather than dictionaries,
|
|
and the ``FILES`` attribute is now a ``MultiValueDict``.
|
|
This brings this class into line with the documentation and with
|
|
``WSGIRequest``.
|
|
|
|
* The :attr:`HttpResponse.charset <django.http.HttpResponse.charset>` attribute
|
|
was added.
|
|
|
|
Tests
|
|
^^^^^
|
|
|
|
* The ``count`` argument was added to
|
|
:meth:`~django.test.SimpleTestCase.assertTemplateUsed`. This allows you to
|
|
assert that a template was rendered a specific number of times.
|
|
|
|
* The new :meth:`~django.test.SimpleTestCase.assertJSONNotEqual` assertion
|
|
allows you to test that two JSON fragments are not equal.
|
|
|
|
* Added the ability to preserve the test database by adding the
|
|
:djadminopt:`--keepdb` flag.
|
|
|
|
* Added the :attr:`~django.test.Response.resolver_match` attribute to test
|
|
client responses.
|
|
|
|
Validators
|
|
^^^^^^^^^^
|
|
|
|
* ...
|
|
|
|
Backwards incompatible changes in 1.8
|
|
=====================================
|
|
|
|
.. warning::
|
|
|
|
In addition to the changes outlined in this section, be sure to review the
|
|
:ref:`deprecation plan <deprecation-removed-in-1.8>` for any features that
|
|
have been removed. If you haven't updated your code within the
|
|
deprecation timeline for a given feature, its removal may appear as a
|
|
backwards incompatible change.
|
|
|
|
Related object operations are run in a transaction
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Some operations on related objects such as
|
|
:meth:`~django.db.models.fields.related.RelatedManager.add()` or
|
|
:ref:`direct assignment<direct-assignment>` ran multiple data modifying
|
|
queries without wrapping them in transactions. To reduce the risk of data
|
|
corruption, all data modifying methods that affect multiple related objects
|
|
(i.e. ``add()``, ``remove()``, ``clear()``, and :ref:`direct assignment
|
|
<direct-assignment>`) now perform their data modifying queries from within a
|
|
transaction, provided your database supports transactions.
|
|
|
|
This has one backwards incompatible side effect, signal handlers triggered from
|
|
these methods are now executed within the method's transaction and any
|
|
exception in a signal handler will prevent the whole operation.
|
|
|
|
Assigning unsaved objects to relations raises an error
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Assigning unsaved objects to a :class:`~django.db.models.ForeignKey`,
|
|
:class:`~django.contrib.contenttypes.fields.GenericForeignKey`, and
|
|
:class:`~django.db.models.OneToOneField` now raises a :exc:`ValueError`.
|
|
|
|
Previously, the assignment of an unsaved object would be silently ignored.
|
|
For example::
|
|
|
|
>>> book = Book.objects.create(name="Django")
|
|
>>> book.author = Author(name="John")
|
|
>>> book.author.save()
|
|
>>> book.save()
|
|
|
|
>>> Book.objects.get(name="Django")
|
|
>>> book.author
|
|
>>>
|
|
|
|
Now, an error will be raised to prevent data loss::
|
|
|
|
>>> book.author = Author(name="john")
|
|
Traceback (most recent call last):
|
|
...
|
|
ValueError: Cannot assign "<Author: John>": "Author" instance isn't saved in the database.
|
|
|
|
Management commands that only accept positional arguments
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
If you have written a custom management command that only accepts positional
|
|
arguments and you didn't specify the
|
|
:attr:`~django.core.management.BaseCommand.args` command variable, you might
|
|
get an error like ``Error: unrecognized arguments: ...``, as variable parsing
|
|
is now based on :py:mod:`argparse` which doesn't implicitly accept positional
|
|
arguments. You can make your command backwards compatible by simply setting the
|
|
:attr:`~django.core.management.BaseCommand.args` class variable. However, if
|
|
you don't have to keep compatibility with older Django versions, it's better to
|
|
implement the new :meth:`~django.core.management.BaseCommand.add_arguments`
|
|
method as described in :doc:`/howto/custom-management-commands`.
|
|
|
|
Custom test management command arguments through test runner
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The method to add custom arguments to the `test` management command through the
|
|
test runner has changed. Previously, you could provide an `option_list` class
|
|
variable on the test runner to add more arguments (à la :py:mod:`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
|
|
:py:class:`argparse.ArgumentParser` instance.
|
|
|
|
Model check ensures auto-generated column names are within limits specified by database
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
A field name that's longer than the column name length supported by a database
|
|
can create problems. For example, with MySQL you'll get an exception trying to
|
|
create the column, and with PostgreSQL the column name is truncated by the
|
|
database (you may see a warning in the PostgreSQL logs).
|
|
|
|
A model check has been introduced to better alert users to this scenario before
|
|
the actual creation of database tables.
|
|
|
|
If you have an existing model where this check seems to be a false positive,
|
|
for example on PostgreSQL where the name was already being truncated, simply
|
|
use :attr:`~django.db.models.Field.db_column` to specify the name that's being
|
|
used.
|
|
|
|
The check also applies to the columns generated in an implicit
|
|
``ManyToManyField.through`` model. If you run into an issue there, use
|
|
:attr:`~django.db.models.ManyToManyField.through` to create an explicit model
|
|
and then specify :attr:`~django.db.models.Field.db_column` on its column(s)
|
|
as needed.
|
|
|
|
Query relation lookups now check object types
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Querying for model lookups now checks if the object passed is of correct type
|
|
and raises a :exc:`ValueError` if not. Previously, Django didn't care if the
|
|
object was of correct type; it just used the object's related field attribute
|
|
(e.g. ``id``) for the lookup. Now, an error is raised to prevent incorrect
|
|
lookups::
|
|
|
|
>>> 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.
|
|
|
|
Default ``EmailField.max_length`` increased to 254
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The old default 75 character ``max_length`` was not capable of storing all
|
|
possible RFC3696/5321-compliant email addresses. In order to store all
|
|
possible valid email addresses, the ``max_length`` has been increased to 254
|
|
characters. You will need to generate and apply database migrations for your
|
|
affected models (or add ``max_length=75`` if you wish to keep the length on
|
|
your current fields). A migration for
|
|
:attr:`django.contrib.auth.models.User.email` is included.
|
|
|
|
Support for PostgreSQL versions older than 9.0
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The end of upstream support periods was reached in July 2014 for PostgreSQL 8.4.
|
|
As a consequence, Django 1.8 sets 9.0 as the minimum PostgreSQL version it
|
|
officially supports.
|
|
|
|
This also includes dropping support for PostGIS 1.3 and 1.4 as these versions
|
|
are not supported on versions of PostgreSQL later than 8.4.
|
|
|
|
Support for MySQL versions older than 5.5
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The end of upstream support periods was reached in January 2012 for MySQL 5.0
|
|
and December 2013 for MySQL 5.1. As a consequence, Django 1.8 sets 5.5 as the
|
|
minimum MySQL version it officially supports.
|
|
|
|
Support for Oracle versions older than 11.1
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The end of upstream support periods was reached in July 2010 for Oracle 9.2,
|
|
January 2012 for Oracle 10.1, and July 2013 for Oracle 10.2. As a consequence,
|
|
Django 1.8 sets 11.1 as the minimum Oracle version it officially supports.
|
|
|
|
``AbstractUser.last_login`` allows null values
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The :attr:`AbstractUser.last_login <django.contrib.auth.models.User.last_login>`
|
|
field now allows null values. Previously, it defaulted to the time when the user
|
|
was created which was misleading if the user never logged in. Please run the
|
|
database migration. If your custom user inherits from ``AbstractUser`` and you
|
|
wish to set ``last_login`` to ``NULL`` for users who haven't logged in, you can
|
|
run this query::
|
|
|
|
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)
|
|
|
|
Miscellaneous
|
|
~~~~~~~~~~~~~
|
|
|
|
* ``connections.queries`` is now a read-only attribute.
|
|
|
|
* Database connections are considered equal only if they're the same object.
|
|
They aren't hashable any more.
|
|
|
|
* :class:`~django.middleware.gzip.GZipMiddleware` used to disable compression
|
|
for some content types when the request is from Internet Explorer, in order
|
|
to work around a bug in IE6 and earlier. This behavior could affect
|
|
performance on IE7 and later. It was removed.
|
|
|
|
* ``URLField.to_python`` no longer adds a trailing slash to pathless URLs.
|
|
|
|
* ``django.contrib.gis`` dropped support for GEOS 3.1 and GDAL 1.6.
|
|
|
|
* The :tfilter:`length` template filter now returns ``0`` for an undefined
|
|
variable, rather than an empty string.
|
|
|
|
* Support for SpatiaLite < 2.4 has been dropped.
|
|
|
|
* ``ForeignKey.default_error_message['invalid']`` has been changed from
|
|
``'%(model)s instance with pk %(pk)r does not exist.'`` to
|
|
``'%(model)s instance with %(field)s %(value)r does not exist.'`` If you are
|
|
using this message in your own code, please update the list of interpolated
|
|
parameters. Internally, Django will continue to provide the
|
|
``pk`` parameter in ``params`` for backwards compatibility.
|
|
|
|
* ``UserCreationForm.errors_messages['duplicate_username']`` is no longer used.
|
|
If you wish to customize that error message, :ref:`override it on the form
|
|
<modelforms-overriding-default-fields>` using the ``'unique'`` key in
|
|
``Meta.errors_messages['username']`` or, if you have a custom form field for
|
|
``'username'``, using the the ``'unique'`` key in its
|
|
:attr:`~django.forms.Field.error_messages` argument.
|
|
|
|
* ``AdminSite`` no longer takes an ``app_name`` argument and its ``app_name``
|
|
attribute has been removed. The application name is always ``admin`` (as
|
|
opposed to the instance name which you can still customize using
|
|
``AdminSite(name="...")``.
|
|
|
|
.. _deprecated-features-1.8:
|
|
|
|
Features deprecated in 1.8
|
|
==========================
|
|
|
|
Loading ``cycle`` and ``firstof`` template tags from ``future`` library
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Django 1.6 introduced ``{% load cycle from future %}`` and
|
|
``{% load firstof from future %}`` syntax for forward compatibility of the
|
|
:ttag:`cycle` and :ttag:`firstof` template tags. This syntax is now deprecated
|
|
and will be removed in Django 2.0. You can simply remove the
|
|
``{% load ... from future %}`` tags.
|
|
|
|
``django.conf.urls.patterns()``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In the olden days of Django, it was encouraged to reference views as strings
|
|
in ``urlpatterns``::
|
|
|
|
urlpatterns = patterns('',
|
|
url('^$', 'myapp.views.myview'),
|
|
)
|
|
|
|
and Django would magically import ``myapp.views.myview`` internally and turn
|
|
the string into a real function reference. In order to reduce repetition when
|
|
referencing many views from the same module, the ``patterns()`` function takes
|
|
a required initial ``prefix`` argument which is prepended to all
|
|
views-as-strings in that set of ``urlpatterns``::
|
|
|
|
urlpatterns = patterns('myapp.views',
|
|
url('^$', 'myview'),
|
|
url('^other/$', 'otherview'),
|
|
)
|
|
|
|
In the modern era, we have updated the tutorial to instead recommend importing
|
|
your views module and referencing your view functions (or classes) directly.
|
|
This has a number of advantages, all deriving from the fact that we are using
|
|
normal Python in place of "Django String Magic": the errors when you mistype a
|
|
view name are less obscure, IDEs can help with autocompletion of view names,
|
|
etc.
|
|
|
|
So these days, the above use of the ``prefix`` arg is much more likely to be
|
|
written (and is better written) as::
|
|
|
|
from myapp import views
|
|
|
|
urlpatterns = patterns('',
|
|
url('^$', views.myview),
|
|
url('^other/$', views.otherview),
|
|
)
|
|
|
|
Thus ``patterns()`` serves little purpose and is a burden when teaching new users
|
|
(answering the newbie's question "why do I need this empty string as the first
|
|
argument to ``patterns()``?"). For these reasons, we are deprecating it.
|
|
Updating your code is as simple as ensuring that ``urlpatterns`` is a list of
|
|
:func:`django.conf.urls.url` instances. For example::
|
|
|
|
from django.conf.urls import url
|
|
from myapp import views
|
|
|
|
urlpatterns = [
|
|
url('^$', views.myview),
|
|
url('^other/$', views.otherview),
|
|
]
|
|
|
|
Passing a string as ``view`` to :func:`~django.conf.urls.url`
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Related to the previous item, referencing views as strings in the ``url()``
|
|
function is deprecated. Pass the callable view as described in the previous
|
|
section instead.
|
|
|
|
``django.test.SimpleTestCase.urls``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The attribute :attr:`SimpleTestCase.urls <django.test.SimpleTestCase.urls>`
|
|
for specifying URLconf configuration in tests has been deprecated and will be
|
|
removed in Django 2.0. Use :func:`@override_settings(ROOT_URLCONF=...)
|
|
<django.test.override_settings>` instead.
|
|
|
|
``prefix`` argument to :func:`~django.conf.urls.i18n.i18n_patterns`
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Related to the previous item, the ``prefix`` argument to
|
|
:func:`django.conf.urls.i18n.i18n_patterns` has been deprecated. Simply pass a
|
|
list of :func:`django.conf.urls.url` instances instead.
|
|
|
|
Using an incorrect count of unpacked values in the :ttag:`for` template tag
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Using an incorrect count of unpacked values in :ttag:`for` tag will raise an
|
|
exception rather than fail silently in Django 2.0.
|
|
|
|
Passing a dotted path to :func:`~django.core.urlresolvers.reverse()` and :ttag:`url`
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Reversing URLs by Python path is an expensive operation as it causes the
|
|
path being reversed to be imported. This behavior has also resulted in a
|
|
`security issue`_. Use :ref:`named URL patterns <naming-url-patterns>`
|
|
for reversing instead.
|
|
|
|
If you are using :mod:`django.contrib.sitemaps`, add the ``name`` argument to
|
|
the ``url`` that references :func:`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')
|
|
|
|
to ensure compatibility when reversing by Python path is removed in Django 2.0.
|
|
|
|
Similarly for GIS sitemaps, add ``name='django.contrib.gis.sitemaps.views.kml'``
|
|
or ``name='django.contrib.gis.sitemaps.views.kmz'``.
|
|
|
|
.. _security issue: https://www.djangoproject.com/weblog/2014/apr/21/security/#s-issue-unexpected-code-execution-using-reverse
|
|
|
|
Extending management command arguments through ``Command.option_list``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Management commands now use :py:mod:`argparse` instead of :py:mod:`optparse` to
|
|
parse command-line arguments passed to commands. This also means that the way
|
|
to add custom arguments to commands has changed: instead of extending the
|
|
``option_list`` class list, you should now override the
|
|
:meth:`~django.core.management.BaseCommand.add_arguments` method and add
|
|
arguments through ``argparse.add_argument()``. See
|
|
:ref:`this example <custom-commands-options>` for more details.
|
|
|
|
``django.core.management.NoArgsCommand``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The class :class:`~django.core.management.NoArgsCommand` is now deprecated and
|
|
will be removed in Django 2.0. Use :class:`~django.core.management.BaseCommand`
|
|
instead, which takes no arguments by default.
|
|
|
|
``cache_choices`` option of ``ModelChoiceField`` and ``ModelMultipleChoiceField``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
:class:`~django.forms.ModelChoiceField` and
|
|
:class:`~django.forms.ModelMultipleChoiceField` took an undocumented, untested
|
|
option ``cache_choices``. This cached querysets between multiple renderings of
|
|
the same ``Form`` object. This option is subject to an accelerated deprecation
|
|
and will be removed in Django 1.9.
|
|
|
|
``django.template.resolve_variable()``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The function has been informally marked as "Deprecated" for some time. Replace
|
|
``resolve_variable(path, context)`` with
|
|
``django.template.Variable(path).resolve(context)``.
|
|
|
|
``django.contrib.webdesign``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
It provided the :ttag:`lorem` template tag which is now included in the
|
|
built-in tags. Simply remove ``'django.contrib.webdesign'`` from
|
|
:setting:`INSTALLED_APPS` and ``{% load webdesign %}`` from your templates.
|
|
|
|
``error_message`` argument to ``django.forms.RegexField``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
It provided backwards compatibility for pre-1.0 code, but its functionality is
|
|
redundant. Use ``Field.error_messages['invalid']`` instead.
|
|
|
|
Old :tfilter:`unordered_list` syntax
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
An older (pre-1.0), more restrictive and verbose input format for the
|
|
:tfilter:`unordered_list` template filter has been deprecated::
|
|
|
|
``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``
|
|
|
|
Using the new syntax, this becomes::
|
|
|
|
``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``
|
|
|
|
``django.forms.Field._has_changed()``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Rename this method to :meth:`~django.forms.Field.has_changed` by removing the
|
|
leading underscore. The old name will still work until Django 2.0.
|
|
|
|
``django.utils.html.remove_tags()`` and ``removetags`` template filter
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
``django.utils.html.remove_tags()`` as well as the template filter
|
|
``removetags`` have been deprecated as they cannot guarantee safe output. Their
|
|
existence is likely to lead to their use in security-sensitive contexts where
|
|
they are not actually safe.
|
|
|
|
The unused and undocumented ``django.utils.html.strip_entities()`` function has
|
|
also been deprecated.
|
|
|
|
``is_admin_site`` argument to ``django.contrib.auth.views.password_reset()``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
It's a legacy option that should no longer be necessary.
|