============================================ Django 1.7 release notes - UNDER DEVELOPMENT ============================================ Welcome to Django 1.7! 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 `, we've `begun the deprecation process for some features`_, and some features have reached the end of their deprecation process and `have been removed`_. .. _`new features`: `What's new in Django 1.7`_ .. _`backwards incompatible changes`: `Backwards incompatible changes in 1.7`_ .. _`begun the deprecation process for some features`: `Features deprecated in 1.7`_ .. _`have been removed`: `Features removed in 1.7`_ Python compatibility ==================== Django 1.7 requires Python 2.7 or above, though we **highly recommend** the latest minor release. Support for Python 2.6 has been dropped and support for Python 3.4 has been added. This change should affect only a small number of Django users, as most operating-system vendors today are shipping Python 2.7 or newer as their default version. If you're still using Python 2.6, however, you'll need to stick to Django 1.6 until you can upgrade your Python version. Per :doc:`our support policy `, Django 1.6 will continue to receive security support until the release of Django 1.8. What's new in Django 1.7 ======================== Schema migrations ~~~~~~~~~~~~~~~~~ Django now has built-in support for schema migrations. It allows models to be updated, changed, and deleted by creating migration files that represent the model changes and which can be run on any development, staging or production database. Migrations are covered in :doc:`their own documentation`, but a few of the key features are: * ``syncdb`` has been deprecated and replaced by ``migrate``. Don't worry - calls to ``syncdb`` will still work as before. * A new ``makemigrations`` command provides an easy way to autodetect changes to your models and make migrations for them. :data:`~django.db.models.signals.pre_syncdb` and :data:`~django.db.models.signals.post_syncdb` have been replaced by :data:`~django.db.models.signals.pre_migrate` and :data:`~django.db.models.signals.post_migrate` respectively. These new signals have slightly different arguments. Check the documentation for details. * The ``allow_syncdb`` method on database routers is now called ``allow_migrate``, but still performs the same function. Routers with ``allow_syncdb`` methods will still work, but that method name is deprecated and you should change it as soon as possible (nothing more than renaming is required). * ``initial_data`` fixtures are no longer loaded for apps with migrations; if you want to load initial data for an app, we suggest you do it in a migration. * Test rollback behavior is different for apps with migrations; in particular, Django will no longer emulate rollbacks on non-transactional databases or inside ``TransactionTestCase`` :ref:`unless specifically requested `. * It is not advised to have apps without migrations depend on (have a :ref:`ForeignKey ` or :ref:`ManyToManyField ` to) apps with migrations. Read the :ref:`dependencies documentation ` for more. * If you are upgrading from South, see our :ref:`upgrading-from-south` documentation, and third-party app authors should read the `South 1.0 release notes `_ for details on how to support South and Django migrations simultaneously. .. _app-loading-refactor-17-release-note: App-loading refactor ~~~~~~~~~~~~~~~~~~~~ Historically, Django applications were tightly linked to models. A singleton known as the "app cache" dealt with both installed applications and models. The models module was used as an identifier for applications in many APIs. As the concept of :doc:`Django applications ` matured, this code showed some shortcomings. It has been refactored into an "app registry" where models modules no longer have a central role and where it's possible to attach configuration data to applications. Improvements thus far include: * Applications can run code at startup, before Django does anything else, with the :meth:`~django.apps.AppConfig.ready` method of their configuration. * Application labels are assigned correctly to models even when they're defined outside of ``models.py``. You don't have to set :attr:`~django.db.models.Options.app_label` explicitly any more. * It is possible to omit ``models.py`` entirely if an application doesn't have any models. * Applications can be relabeled with the :attr:`~django.apps.AppConfig.label` attribute of application configurations, to work around label conflicts. * The name of applications can be customized in the admin with the :attr:`~django.apps.AppConfig.verbose_name` of application configurations. * The admin automatically calls :func:`~django.contrib.admin.autodiscover()` when Django starts. You can consequently remove this line from your URLconf. * Django imports all application configurations and models as soon as it starts, through a deterministic and straightforward process. This should make it easier to diagnose import issues such as import loops. New method on Field subclasses ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To help power both schema migrations and composite keys, the :class:`~django.db.models.Field` API now has a new required method: ``deconstruct()``. This method takes no arguments, and returns a tuple of four items: * ``name``: The field's attribute name on its parent model, or None if it is not part of a model * ``path``: A dotted, Python path to the class of this field, including the class name. * ``args``: Positional arguments, as a list * ``kwargs``: Keyword arguments, as a dict These four values allow any field to be serialized into a file, as well as allowing the field to be copied safely, both essential parts of these new features. This change should not affect you unless you write custom Field subclasses; if you do, you may need to reimplement the ``deconstruct()`` method if your subclass changes the method signature of ``__init__`` in any way. If your field just inherits from a built-in Django field and doesn't override ``__init__``, no changes are necessary. If you do need to override ``deconstruct()``, a good place to start is the built-in Django fields (``django/db/models/fields/__init__.py``) as several fields, including ``DecimalField`` and ``DateField``, override it and show how to call the method on the superclass and simply add or remove extra arguments. This also means that all arguments to fields must themselves be serializable; to see what we consider serializable, and to find out how to make your own classes serializable, read the :ref:`migration serialization documentation `. Calling custom ``QuerySet`` methods from the ``Manager`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historically, the recommended way to make reusable model queries was to create methods on a custom ``Manager`` class. The problem with this approach was that after the first method call, you'd get back a ``QuerySet`` instance and couldn't call additional custom manager methods. Though not documented, it was common to work around this issue by creating a custom ``QuerySet`` so that custom methods could be chained; but the solution had a number of drawbacks: * The custom ``QuerySet`` and its custom methods were lost after the first call to ``values()`` or ``values_list()``. * Writing a custom ``Manager`` was still necessary to return the custom ``QuerySet`` class and all methods that were desired on the ``Manager`` had to be proxied to the ``QuerySet``. The whole process went against the DRY principle. The :meth:`QuerySet.as_manager() ` class method can now directly :ref:`create Manager with QuerySet methods `:: class FoodQuerySet(models.QuerySet): def pizzas(self): return self.filter(kind='pizza') def vegetarian(self): return self.filter(vegetarian=True) class Food(models.Model): kind = models.CharField(max_length=50) vegetarian = models.BooleanField(default=False) objects = FoodQuerySet.as_manager() Food.objects.pizzas().vegetarian() Using a custom manager when traversing reverse relations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It is now possible to :ref:`specify a custom manager ` when traversing a reverse relationship:: class Blog(models.Model): pass class Entry(models.Model): blog = models.ForeignKey(Blog) objects = models.Manager() # Default Manager entries = EntryManager() # Custom Manager b = Blog.objects.get(id=1) b.entry_set(manager='entries').all() New system check framework ~~~~~~~~~~~~~~~~~~~~~~~~~~ We've added a new :doc:`System check framework ` for detecting common problems (like invalid models) and providing hints for resolving those problems. The framework is extensible so you can add your own checks for your own apps and libraries. To perform system checks, you use the :djadmin:`check` management command. This command replaces the older :djadmin:`validate` management command. New ``Prefetch`` object for advanced ``prefetch_related`` operations. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The new :class:`~django.db.models.Prefetch` object allows customizing prefetch operations. You can specify the ``QuerySet`` used to traverse a given relation or customize the storage location of prefetch results. This enables things like filtering prefetched relations, calling :meth:`~django.db.models.query.QuerySet.select_related()` from a prefetched relation, or prefetching the same relation multiple times with different querysets. See :meth:`~django.db.models.query.QuerySet.prefetch_related()` for more details. Admin shortcuts support time zones ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The "today" and "now" shortcuts next to date and time input widgets in the admin are now operating in the :ref:`current time zone `. Previously, they used the browser time zone, which could result in saving the wrong value when it didn't match the current time zone on the server. In addition, the widgets now display a help message when the browser and server time zone are different, to clarify how the value inserted in the field will be interpreted. Using database cursors as context managers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prior to Python 2.7, database cursors could be used as a context manager. The specific backend's cursor defined the behavior of the context manager. The behavior of magic method lookups was changed with Python 2.7 and cursors were no longer usable as context managers. Django 1.7 allows a cursor to be used as a context manager that is a shortcut for the following, instead of backend specific behavior:: c = connection.cursor() try: c.execute(...) finally: c.close() Custom lookups ~~~~~~~~~~~~~~ It is now possible to write custom lookups and transforms for the ORM. Custom lookups work just like Django's inbuilt lookups (e.g. ``lte``, ``icontains``) while transforms are a new concept. The :class:`django.db.models.Lookup` class provides a way to add lookup operators for model fields. As an example it is possible to add ``day_lte`` operator for ``DateFields``. The :class:`django.db.models.Transform` class allows transformations of database values prior to the final lookup. For example it is possible to write a ``year`` transform that extracts year from the field's value. Transforms allow for chaining. After the ``year`` transform has been added to ``DateField`` it is possible to filter on the transformed value, for example ``qs.filter(author__birthdate__year__lte=1981)``. For more information about both custom lookups and transforms refer to :doc:`custom lookups ` documentation. Improvements to ``Form`` error handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``Form.add_error()`` ^^^^^^^^^^^^^^^^^^^^ Previously there were two main patterns for handling errors in forms: * Raising a :exc:`~django.core.exceptions.ValidationError` from within certain functions (e.g. ``Field.clean()``, ``Form.clean_()``, or ``Form.clean()`` for non-field errors.) * Fiddling with ``Form._errors`` when targeting a specific field in ``Form.clean()`` or adding errors from outside of a "clean" method (e.g. directly from a view). Using the former pattern was straightforward since the form can guess from the context (i.e. which method raised the exception) where the errors belong and automatically process them. This remains the canonical way of adding errors when possible. However the latter was fiddly and error-prone, since the burden of handling edge cases fell on the user. The new :meth:`~django.forms.Form.add_error()` method allows adding errors to specific form fields from anywhere without having to worry about the details such as creating instances of ``django.forms.utils.ErrorList`` or dealing with ``Form.cleaned_data``. This new API replaces manipulating ``Form._errors`` which now becomes a private API. See :ref:`validating-fields-with-clean` for an example using ``Form.add_error()``. Error metadata ^^^^^^^^^^^^^^ The :exc:`~django.core.exceptions.ValidationError` constructor accepts metadata such as error ``code`` or ``params`` which are then available for interpolating into the error message (see :ref:`raising-validation-error` for more details); however, before Django 1.7 those metadata were discarded as soon as the errors were added to :attr:`Form.errors `. :attr:`Form.errors ` and ``django.forms.utils.ErrorList`` now store the ``ValidationError`` instances so these metadata can be retrieved at any time through the new :meth:`Form.errors.as_data ` method. The retrieved ``ValidationError`` instances can then be identified thanks to their error ``code`` which enables things like rewriting the error's message or writing custom logic in a view when a given error is present. It can also be used to serialize the errors in a custom format such as XML. The new :meth:`Form.errors.as_json() ` method is a convenience method which returns error messages along with error codes serialized as JSON. ``as_json()`` uses ``as_data()`` and gives an idea of how the new system could be extended. Error containers and backward compatibility ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Heavy changes to the various error containers were necessary in order to support the features above, specifically :attr:`Form.errors `, ``django.forms.utils.ErrorList``, and the internal storages of :exc:`~django.core.exceptions.ValidationError`. These containers which used to store error strings now store ``ValidationError`` instances and public APIs have been adapted to make this as transparent as possible, but if you've been using private APIs, some of the changes are backwards incompatible; see :ref:`validation-error-constructor-and-internal-storage` for more details. Minor features ~~~~~~~~~~~~~~ :mod:`django.contrib.admin` ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * You can now implement :attr:`~django.contrib.admin.AdminSite.site_header`, :attr:`~django.contrib.admin.AdminSite.site_title`, and :attr:`~django.contrib.admin.AdminSite.index_title` attributes on a custom :class:`~django.contrib.admin.AdminSite` in order to easily change the admin site's page title and header text. No more needing to override templates! * Buttons in :mod:`django.contrib.admin` now use the ``border-radius`` CSS property for rounded corners rather than GIF background images. * Some admin templates now have ``app-`` and ``model-`` classes in their ```` tag to allow customizing the CSS per app or per model. * The admin changelist cells now have a ``field-`` class in the HTML to enable style customizations. * The admin's search fields can now be customized per-request thanks to the new :meth:`django.contrib.admin.ModelAdmin.get_search_fields` method. * The :meth:`ModelAdmin.get_fields() ` method may be overridden to customize the value of :attr:`ModelAdmin.fields `. * In addition to the existing ``admin.site.register`` syntax, you can use the new :func:`~django.contrib.admin.register` decorator to register a :class:`~django.contrib.admin.ModelAdmin`. * You may specify :meth:`ModelAdmin.list_display_links ` ``= None`` to disable links on the change list page grid. * You may now specify :attr:`ModelAdmin.view_on_site ` to control whether or not to display the "View on site" link. * You can specify a descending ordering for a :attr:`ModelAdmin.list_display ` value by prefixing the ``admin_order_field`` value with a hyphen. * The :meth:`ModelAdmin.get_changeform_initial_data() ` method may be overridden to define custom behavior for setting initial change form data. :mod:`django.contrib.auth` ^^^^^^^^^^^^^^^^^^^^^^^^^^ * Any ``**kwargs`` passed to :meth:`~django.contrib.auth.models.User.email_user()` are passed to the underlying :meth:`~django.core.mail.send_mail()` call. * The :func:`~django.contrib.auth.decorators.permission_required` decorator can take a list of permissions as well as a single permission. * You can override the new :meth:`AuthenticationForm.confirm_login_allowed() ` method to more easily customize the login policy. * :func:`django.contrib.auth.views.password_reset` takes an optional ``html_email_template_name`` parameter used to send a multipart HTML email for password resets. * The :meth:`AbstractBaseUser.get_session_auth_hash() ` method was added and if your :setting:`AUTH_USER_MODEL` inherits from :class:`~django.contrib.auth.models.AbstractBaseUser`, changing a user's password now invalidates old sessions if the :class:`~django.contrib.auth.middleware.SessionAuthenticationMiddleware` is enabled. See :ref:`session-invalidation-on-password-change` for more details including upgrade considerations when enabling this new middleware. :mod:`django.contrib.formtools` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Calls to :meth:`WizardView.done() ` now include a ``form_dict`` to allow easier access to forms by their step name. :mod:`django.contrib.gis` ^^^^^^^^^^^^^^^^^^^^^^^^^^ * The default OpenLayers library version included in widgets has been updated from 2.11 to 2.13. * Prepared geometries now also support the ``crosses``, ``disjoint``, ``overlaps``, ``touches`` and ``within`` predicates, if GEOS 3.3 or later is installed. :mod:`django.contrib.messages` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * The backends for :mod:`django.contrib.messages` that use cookies, will now follow the :setting:`SESSION_COOKIE_SECURE` and :setting:`SESSION_COOKIE_HTTPONLY` settings. * The :ref:`messages context processor ` now adds a dictionary of default levels under the name ``DEFAULT_MESSAGE_LEVELS``. * :class:`~django.contrib.messages.storage.base.Message` objects now have a ``level_tag`` attribute that contains the string representation of the message level. :mod:`django.contrib.redirects` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * :class:`~django.contrib.redirects.middleware.RedirectFallbackMiddleware` has two new attributes (:attr:`~django.contrib.redirects.middleware.RedirectFallbackMiddleware.response_gone_class` and :attr:`~django.contrib.redirects.middleware.RedirectFallbackMiddleware.response_redirect_class`) that specify the types of :class:`~django.http.HttpResponse` instances the middleware returns. :mod:`django.contrib.sessions` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * The ``"django.contrib.sessions.backends.cached_db"`` session backend now respects :setting:`SESSION_CACHE_ALIAS`. In previous versions, it always used the `default` cache. :mod:`django.contrib.sitemaps` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * The :mod:`sitemap framework` now makes use of :attr:`~django.contrib.sitemaps.Sitemap.lastmod` to set a ``Last-Modified`` header in the response. This makes it possible for the :class:`~django.middleware.http.ConditionalGetMiddleware` to handle conditional ``GET`` requests for sitemaps which set ``lastmod``. :mod:`django.contrib.sites` ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * The new :class:`django.contrib.sites.middleware.CurrentSiteMiddleware` allows setting the current site on each request. :mod:`django.contrib.staticfiles` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * The :ref:`static files storage classes ` may be subclassed to override the permissions that collected static files and directories receive by setting the :attr:`~django.core.files.storage.FileSystemStorage.file_permissions_mode` and :attr:`~django.core.files.storage.FileSystemStorage.directory_permissions_mode` parameters. See :djadmin:`collectstatic` for example usage. * The :class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage` backend gets a sibling class called :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` that doesn't use the cache system at all but instead a JSON file called ``staticfiles.json`` for storing the mapping between the original file name (e.g. ``css/styles.css``) and the hashed file name (e.g. ``css/styles.55e7cbb9ba48.css``. The ``staticfiles.json`` file is created when running the :djadmin:`collectstatic` management command and should be a less expensive alternative for remote storages such as Amazon S3. See the :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` docs for more information. * :djadmin:`findstatic` now accepts verbosity flag level 2, meaning it will show the relative paths of the directories it searched. See :djadmin:`findstatic` for example output. :mod:`django.contrib.syndication` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * The :class:`~django.utils.feedgenerator.Atom1Feed` syndication feed's ``updated`` element now utilizes ``updateddate`` instead of ``pubdate``, allowing the ``published`` element to be included in the feed (which relies on ``pubdate``). Cache ^^^^^ * Access to caches configured in :setting:`CACHES` is now available via :data:`django.core.cache.caches`. This dict-like object provides a different instance per thread. It supersedes :func:`django.core.cache.get_cache` which is now deprecated. * If you instantiate cache backends directly, be aware that they aren't thread-safe any more, as :data:`django.core.cache.caches` now yields different instances per thread. * Defining the :setting:`TIMEOUT ` argument of the :setting:`CACHES` setting as ``None`` will set the cache keys as "non-expiring" by default. Previously, it was only possible to pass ``timeout=None`` to the cache backend's ``set()`` method. Cross Site Request Forgery ^^^^^^^^^^^^^^^^^^^^^^^^^^ * The :setting:`CSRF_COOKIE_AGE` setting facilitates the use of session-based CSRF cookies. Email ^^^^^ * :func:`~django.core.mail.send_mail` now accepts an ``html_message`` parameter for sending a multipart ``text/plain`` and ``text/html`` email. * The SMTP :class:`~django.core.mail.backends.smtp.EmailBackend` now accepts a :attr:`~django.core.mail.backends.smtp.EmailBackend.timeout` parameter. File Storage ^^^^^^^^^^^^ * File locking on Windows previously depended on the PyWin32 package; if it wasn't installed, file locking failed silently. That dependency has been removed, and file locking is now implemented natively on both Windows and Unix. File Uploads ^^^^^^^^^^^^ * The new :attr:`UploadedFile.content_type_extra ` attribute contains extra parameters passed to the ``content-type`` header on a file upload. * The new :setting:`FILE_UPLOAD_DIRECTORY_PERMISSIONS` setting controls the file system permissions of directories created during file upload, like :setting:`FILE_UPLOAD_PERMISSIONS` does for the files themselves. * The :attr:`FileField.upload_to ` attribute is now optional. If it is omitted or given ``None`` or an empty string, a subdirectory won't be used for storing the uploaded files. * Uploaded files are now explicitly closed before the response is delivered to the client. Partially uploaded files are also closed as long as they are named ``file`` in the upload handler. Forms ^^^^^ * The ``