1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177 |
- ========================
- Django 1.2 release notes
- ========================
- *May 17, 2010.*
- Welcome to Django 1.2!
- Nearly a year in the making, Django 1.2 packs an impressive list of `new
- features`_ and lots of bug fixes. These release notes cover the new features,
- as well as important changes you'll want to be aware of when upgrading from
- Django 1.1 or older versions.
- .. _new features: `What's new in Django 1.2`_
- Overview
- ========
- Django 1.2 introduces several large, important new features, including:
- * Support for `multiple database connections`_ in a single Django instance.
- * `Model validation`_ inspired by Django's form validation.
- * Vastly `improved protection against Cross-Site Request Forgery`_ (CSRF).
- * A new `user "messages" framework`_ with support for cookie- and session-based
- message for both anonymous and authenticated users.
- * Hooks for `object-level permissions`_, `permissions for anonymous users`_,
- and `more flexible username requirements`_.
- * Customization of email sending via `email backends`_.
- * New :ref:`"smart" if template tag <new-in-1.2-smart-if>` which supports
- comparison operators.
- .. _multiple database connections: `support for multiple databases`_
- .. _improved protection against Cross-Site Request Forgery: `improved CSRF protection`_
- .. _user "messages" framework: `messages framework`_
- .. _more flexible username requirements: `relaxed requirements for usernames`_
- These are just the highlights; full details and a complete list of features `may
- be found below`_.
- .. _may be found below: `What's new in Django 1.2`_
- .. seealso::
- `Django Advent`_ covered the release of Django 1.2 with a series of
- articles and tutorials that cover some of the new features in depth.
- .. _django advent: https://github.com/djangoadvent/djangoadvent-articles
- Wherever possible these features have been introduced in a backwards-compatible
- manner per :doc:`our API stability policy </misc/api-stability>` policy.
- However, a handful of features *have* changed in ways that, for some users, will be
- backwards-incompatible. The big changes are:
- * Support for Python 2.3 has been dropped. See the full notes
- below.
- * The new CSRF protection framework is not backwards-compatible with
- the old system. Users of the old system will not be affected until
- the old system is removed in Django 1.4.
- However, upgrading to the new CSRF protection framework requires a few
- important backwards-incompatible changes, detailed in `CSRF Protection`_,
- below.
- * Authors of custom :class:`~django.db.models.Field` subclasses should be
- aware that a number of methods have had a change in prototype, detailed
- under `get_db_prep_*() methods on Field`_, below.
- * The internals of template tags have changed somewhat; authors of custom
- template tags that need to store state (e.g. custom control flow tags)
- should ensure that their code follows the new rules for `stateful template
- tags`_
- * The :func:`~django.contrib.auth.decorators.user_passes_test`,
- :func:`~django.contrib.auth.decorators.login_required`, and
- :func:`~django.contrib.auth.decorators.permission_required`, decorators
- from :mod:`django.contrib.auth` only apply to functions and no longer
- work on methods. There's a simple one-line fix `detailed below`_.
- .. _detailed below: `user_passes_test, login_required and permission_required`_
- Again, these are just the big features that will affect the most users. Users
- upgrading from previous versions of Django are heavily encouraged to consult
- the complete list of :ref:`backwards-incompatible changes
- <backwards-incompatible-changes-1.2>` and the list of :ref:`deprecated
- features <deprecated-features-1.2>`.
- Python compatibility
- ====================
- While not a new feature, it's important to note that Django 1.2
- introduces the first shift in our Python compatibility policy since
- Django's initial public debut. Previous Django releases were tested
- and supported on 2.x Python versions from 2.3 up; Django 1.2, however,
- drops official support for Python 2.3. As such, the minimum Python
- version required for Django is now 2.4, and Django is tested and
- supported on Python 2.4, 2.5 and 2.6, and will be supported on the
- as-yet-unreleased Python 2.7.
- This change should affect only a small number of Django users, as most
- operating-system vendors today are shipping Python 2.4 or newer as
- their default version. If you're still using Python 2.3, however,
- you'll need to stick to Django 1.1 until you can upgrade; per
- :doc:`our support policy </internals/release-process>`, Django 1.1 will
- continue to receive security support until the release of Django 1.3.
- A roadmap for Django's overall 2.x Python support, and eventual
- transition to Python 3.x, is currently being developed, and will be
- announced prior to the release of Django 1.3.
- What's new in Django 1.2
- ========================
- Support for multiple databases
- ------------------------------
- Django 1.2 adds the ability to use :doc:`more than one database
- </topics/db/multi-db>` in your Django project. Queries can be issued at a
- specific database with the ``using()`` method on ``QuerySet`` objects.
- Individual objects can be saved to a specific database by providing a ``using``
- argument when you call ``save()``.
- Model validation
- ----------------
- Model instances now have support for :ref:`validating their own data
- <validating-objects>`, and both model and form fields now accept configurable
- lists of :doc:`validators </ref/validators>` specifying reusable, encapsulated
- validation behavior. Note, however, that validation must still be performed
- explicitly. Simply invoking a model instance's ``save()`` method will not
- perform any validation of the instance's data.
- Improved CSRF protection
- ------------------------
- Django now has much improved protection against :doc:`Cross-Site Request Forgery
- (CSRF) attacks</ref/csrf>`. This type of attack occurs when a malicious
- Web site contains a link, a form button or some JavaScript that is intended to
- perform some action on your Web site, using the credentials of a logged-in user
- who visits the malicious site in their browser. A related type of attack, "login
- CSRF," where an attacking site tricks a user's browser into logging into a site
- with someone else's credentials, is also covered.
- Messages framework
- ------------------
- Django now includes a robust and configurable :doc:`messages framework
- </ref/contrib/messages>` with built-in support for cookie- and session-based
- messaging, for both anonymous and authenticated clients. The messages framework
- replaces the deprecated user message API and allows you to temporarily store
- messages in one request and retrieve them for display in a subsequent request
- (usually the next one).
- Object-level permissions
- ------------------------
- A foundation for specifying permissions at the per-object level has been added.
- Although there is no implementation of this in core, a custom authentication
- backend can provide this implementation and it will be used by
- :class:`django.contrib.auth.models.User`. See the :doc:`authentication docs
- </topics/auth/index>` for more information.
- Permissions for anonymous users
- -------------------------------
- If you provide a custom auth backend with ``supports_anonymous_user`` set to
- ``True``, AnonymousUser will check the backend for permissions, just like
- User already did. This is useful for centralizing permission handling - apps
- can always delegate the question of whether something is allowed or not to
- the authorization/authentication backend. See the :doc:`authentication
- docs </topics/auth/index>` for more details.
- Relaxed requirements for usernames
- ----------------------------------
- The built-in :class:`~django.contrib.auth.models.User` model's
- :attr:`~django.contrib.auth.models.User.username` field now allows a wider range
- of characters, including ``@``, ``+``, ``.`` and ``-`` characters.
- Email backends
- --------------
- You can now :ref:`configure the way that Django sends email
- <topic-email-backends>`. Instead of using SMTP to send all email, you
- can now choose a configurable email backend to send messages. If your
- hosting provider uses a sandbox or some other non-SMTP technique for
- sending mail, you can now construct an email backend that will allow
- Django's standard :doc:`mail sending methods</topics/email>` to use
- those facilities.
- This also makes it easier to debug mail sending. Django ships with
- backend implementations that allow you to send email to a
- :ref:`file<topic-email-file-backend>`, to the
- :ref:`console<topic-email-console-backend>`, or to
- :ref:`memory<topic-email-memory-backend>`. You can even configure all
- email to be :ref:`thrown away<topic-email-dummy-backend>`.
- .. _new-in-1.2-smart-if:
- "Smart" :ttag:`if` tag
- ----------------------
- The :ttag:`if` tag has been upgraded to be much more powerful. First, we've
- added support for comparison operators. No longer will you have to type:
- .. code-block:: html+django
- {% ifnotequal a b %}
- ...
- {% endifnotequal %}
- You can now do this:
- .. code-block:: html+django
- {% if a != b %}
- ...
- {% endif %}
- There's really no reason to use ``{% ifequal %}`` or ``{% ifnotequal %}``
- anymore, unless you're the nostalgic type.
- The operators supported are ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=``,
- ``in`` and ``not in``, all of which work like the Python operators, in addition
- to ``and``, ``or`` and ``not``, which were already supported.
- Also, filters may now be used in the ``if`` expression. For example:
- .. code-block:: html+django
- <div
- {% if user.email|lower == message.recipient|lower %}
- class="highlight"
- {% endif %}
- >{{ message }}</div>
- Template caching
- ----------------
- In previous versions of Django, every time you rendered a template, it
- would be reloaded from disk. In Django 1.2, you can use a :ref:`cached
- template loader <template-loaders>` to load templates once, then
- cache the result for every subsequent render. This can lead to a
- significant performance improvement if your templates are broken into
- lots of smaller subtemplates (using the ``{% extends %}`` or ``{%
- include %}`` tags).
- As a side effect, it is now much easier to support non-Django template
- languages. For more details, see the :ref:`notes on supporting
- non-Django template languages<topic-template-alternate-language>`.
- Class-based template loaders
- ----------------------------
- As part of the changes made to introduce `Template caching`_ and following
- a general trend in Django, the template loaders API has been modified
- to use template loading mechanisms that are encapsulated in Python classes as
- opposed to functions, the only method available until Django 1.1.
- All the template loaders :ref:`shipped with Django <template-loaders>` have
- been ported to the new API but they still implement the function-based API and
- the template core machinery still accepts function-based loaders (builtin or
- third party) so there is no immediate need to modify your
- :setting:`TEMPLATE_LOADERS` setting in existing projects, things will keep
- working if you leave it untouched up to and including the Django 1.3 release.
- If you have developed your own custom template loaders we suggest to consider
- porting them to a class-based implementation because the code for backwards
- compatibility with function-based loaders starts its deprecation process in
- Django 1.2 and will be removed in Django 1.4. There is a description of the
- API these loader classes must implement :ref:`here
- <topic-template-alternate-language>` and you can also examine the source code
- of the loaders shipped with Django.
- Natural keys in fixtures
- ------------------------
- Fixtures can now refer to remote objects using
- :ref:`topics-serialization-natural-keys`. This lookup scheme is an
- alternative to the normal primary-key based object references in a
- fixture, improving readability and resolving problems referring to
- objects whose primary key value may not be predictable or known.
- Fast failure for tests
- ----------------------
- Both the :djadmin:`test` subcommand of ``django-admin.py`` and the
- ``runtests.py`` script used to run Django's own test suite now support a
- ``--failfast`` option. When specified, this option causes the test runner to
- exit after encountering a failure instead of continuing with the test run. In
- addition, the handling of ``Ctrl-C`` during a test run has been improved to
- trigger a graceful exit from the test run that reports details of the tests that
- were run before the interruption.
- ``BigIntegerField``
- -------------------
- Models can now use a 64-bit :class:`~django.db.models.BigIntegerField` type.
- Improved localization
- ---------------------
- Django's :doc:`internationalization framework </topics/i18n/index>` has been expanded
- with locale-aware formatting and form processing. That means, if enabled, dates
- and numbers on templates will be displayed using the format specified for the
- current locale. Django will also use localized formats when parsing data in
- forms. See :ref:`Format localization <format-localization>` for more details.
- ``readonly_fields`` in ``ModelAdmin``
- -------------------------------------
- :attr:`django.contrib.admin.ModelAdmin.readonly_fields` has been added to
- enable non-editable fields in add/change pages for models and inlines. Field
- and calculated values can be displayed alongside editable fields.
- Customizable syntax highlighting
- --------------------------------
- You can now use a ``DJANGO_COLORS`` environment variable to modify or disable
- the colors used by ``django-admin.py`` to provide :ref:`syntax highlighting
- <syntax-coloring>`.
- Syndication feeds as views
- --------------------------
- :doc:`Syndication feeds </ref/contrib/syndication>` can now be used directly as
- views in your :doc:`URLconf </topics/http/urls>`. This means that you can
- maintain complete control over the URL structure of your feeds. Like any other
- view, feeds views are passed a ``request`` object, so you can do anything you
- would normally do with a view, like user based access control, or making a feed
- a named URL.
- GeoDjango
- ---------
- The most significant new feature for :doc:`GeoDjango </ref/contrib/gis/index>`
- in 1.2 is support for multiple spatial databases. As a result,
- the following :ref:`spatial database backends <spatial-backends>`
- are now included:
- * ``django.contrib.gis.db.backends.postgis``
- * ``django.contrib.gis.db.backends.mysql``
- * ``django.contrib.gis.db.backends.oracle``
- * ``django.contrib.gis.db.backends.spatialite``
- GeoDjango now supports the rich capabilities added
- in the `PostGIS 1.5 release <http://postgis.refractions.net/documentation/manual-1.5/>`_.
- New features include support for the :ref:`geography type <geography-type>`
- and enabling of :ref:`distance queries <distance-queries>`
- with non-point geometries on geographic coordinate systems.
- Support for 3D geometry fields was added, and may be enabled
- by setting the :attr:`~django.contrib.gis.db.models.GeometryField.dim`
- keyword to 3 in your :class:`~django.contrib.gis.db.models.GeometryField`.
- The :class:`~django.contrib.gis.db.models.Extent3D` aggregate
- and :meth:`~django.contrib.gis.db.models.GeoQuerySet.extent3d` ``GeoQuerySet``
- method were added as a part of this feature.
- The following :class:`~django.contrib.gis.db.models.GeoQuerySet`
- methods are new in 1.2:
- * :meth:`~django.contrib.gis.db.models.GeoQuerySet.force_rhr`
- * :meth:`~django.contrib.gis.db.models.GeoQuerySet.reverse_geom`
- * :meth:`~django.contrib.gis.db.models.GeoQuerySet.geohash`
- The :ref:`GEOS interface <ref-geos>` was updated to use
- thread-safe C library functions when available on the platform.
- The :ref:`GDAL interface <ref-gdal>` now allows the user to
- set a :attr:`~django.contrib.gis.gdal.Layer.spatial_filter` on
- the features returned when iterating over a
- :class:`~django.contrib.gis.gdal.Layer`.
- Finally, :doc:`GeoDjango's documentation </ref/contrib/gis/index>` is now
- included with Django's and is no longer
- hosted separately at `geodjango.org <http://geodjango.org/>`_.
- .. _1.2-js-assisted-inlines:
- JavaScript-assisted handling of inline related objects in the admin
- -------------------------------------------------------------------
- If a user has JavaScript enabled in their browser, the interface for
- inline objects in the admin now allows inline objects to be
- dynamically added and removed. Users without JavaScript-enabled
- browsers will see no change in the behavior of inline objects.
- New ``now`` template tag format specifier characters: ``c`` and ``u``
- ---------------------------------------------------------------------
- The argument to the :ttag:`now` has gained two new format characters:
- ``c`` to specify that a datetime value should be formatted in ISO 8601
- format, and ``u`` that allows output of the microseconds part of a
- datetime or time value.
- These are also available in others parts like the :tfilter:`date` and
- :tfilter:`time` template filters, the ``humanize`` template tag library
- and the new `format localization`_ framework.
- .. _format localization: `Improved localization`_
- .. _backwards-incompatible-changes-1.2:
- Backwards-incompatible changes in 1.2
- =====================================
- Wherever possible the new features above have been introduced in a
- backwards-compatible manner per :doc:`our API stability policy
- </misc/api-stability>` policy. This means that practically all existing
- code which worked with Django 1.1 will continue to work with Django
- 1.2; such code will, however, begin issuing warnings (see below for
- details).
- However, a handful of features *have* changed in ways that, for some
- users, will be immediately backwards-incompatible. Those changes are
- detailed below.
- CSRF Protection
- ---------------
- We've made large changes to the way CSRF protection works, detailed in
- :doc:`the CSRF documentation </ref/csrf>`. Here are the major changes you
- should be aware of:
- * ``CsrfResponseMiddleware`` and ``CsrfMiddleware`` have been deprecated and
- will be removed completely in Django 1.4, in favor of a template tag that
- should be inserted into forms.
- * All contrib apps use a ``csrf_protect`` decorator to protect the view. This
- requires the use of the ``csrf_token`` template tag in the template. If you
- have used custom templates for contrib views, you MUST READ THE UPGRADE
- INSTRUCTIONS to fix those templates.
- .. admonition:: Documentation removed
- The upgrade notes have been removed in current Django docs. Please refer
- to the docs for Django 1.3 or older to find these instructions.
- * ``CsrfViewMiddleware`` is included in :setting:`MIDDLEWARE_CLASSES` by
- default. This turns on CSRF protection by default, so views that accept
- POST requests need to be written to work with the middleware. Instructions
- on how to do this are found in the CSRF docs.
- * All of the CSRF has moved from contrib to core (with backwards
- compatible imports in the old locations, which are deprecated and
- will cease to be supported in Django 1.4).
- ``get_db_prep_*()`` methods on ``Field``
- ----------------------------------------
- Prior to Django 1.2, a custom ``Field`` had the option of defining
- several functions to support conversion of Python values into
- database-compatible values. A custom field might look something like::
- class CustomModelField(models.Field):
- # ...
- def db_type(self):
- # ...
- def get_db_prep_save(self, value):
- # ...
- def get_db_prep_value(self, value):
- # ...
- def get_db_prep_lookup(self, lookup_type, value):
- # ...
- In 1.2, these three methods have undergone a change in prototype, and
- two extra methods have been introduced::
- class CustomModelField(models.Field):
- # ...
- def db_type(self, connection):
- # ...
- def get_prep_value(self, value):
- # ...
- def get_prep_lookup(self, lookup_type, value):
- # ...
- def get_db_prep_save(self, value, connection):
- # ...
- def get_db_prep_value(self, value, connection, prepared=False):
- # ...
- def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
- # ...
- These changes are required to support multiple databases --
- ``db_type`` and ``get_db_prep_*`` can no longer make any assumptions
- regarding the database for which it is preparing. The ``connection``
- argument now provides the preparation methods with the specific
- connection for which the value is being prepared.
- The two new methods exist to differentiate general data-preparation
- requirements from requirements that are database-specific. The
- ``prepared`` argument is used to indicate to the database-preparation
- methods whether generic value preparation has been performed. If
- an unprepared (i.e., ``prepared=False``) value is provided to the
- ``get_db_prep_*()`` calls, they should invoke the corresponding
- ``get_prep_*()`` calls to perform generic data preparation.
- We've provided conversion functions that will transparently
- convert functions adhering to the old prototype into functions
- compatible with the new prototype. However, these conversion functions
- will be removed in Django 1.4, so you should upgrade your ``Field``
- definitions to use the new prototype as soon as possible.
- If your ``get_db_prep_*()`` methods made no use of the database
- connection, you should be able to upgrade by renaming
- ``get_db_prep_value()`` to ``get_prep_value()`` and
- ``get_db_prep_lookup()`` to ``get_prep_lookup()``. If you require
- database specific conversions, then you will need to provide an
- implementation ``get_db_prep_*`` that uses the ``connection``
- argument to resolve database-specific values.
- Stateful template tags
- ----------------------
- Template tags that store rendering state on their ``Node`` subclass
- have always been vulnerable to thread-safety and other issues; as of
- Django 1.2, however, they may also cause problems when used with the
- new :ref:`cached template loader<template-loaders>`.
- All of the built-in Django template tags are safe to use with the cached
- loader, but if you're using custom template tags that come from third
- party packages, or from your own code, you should ensure that the
- ``Node`` implementation for each tag is thread-safe. For more
- information, see
- :ref:`template tag thread safety considerations<template_tag_thread_safety>`.
- You may also need to update your templates if you were relying on the
- implementation of Django's template tags *not* being thread safe. The
- :ttag:`cycle` tag is the most likely to be affected in this way,
- especially when used in conjunction with the :ttag:`include` tag.
- Consider the following template fragment::
- {% for object in object_list %}
- {% include "subtemplate.html" %}
- {% endfor %}
- with a ``subtemplate.html`` that reads::
- {% cycle 'even' 'odd' %}
- Using the non-thread-safe, pre-Django 1.2 renderer, this would output::
- even odd even odd ...
- Using the thread-safe Django 1.2 renderer, you will instead get::
- even even even even ...
- This is because each rendering of the :ttag:`include` tag is an
- independent rendering. When the :ttag:`cycle` tag was not thread safe,
- the state of the :ttag:`cycle` tag would leak between multiple
- renderings of the same :ttag:`include`. Now that the :ttag:`cycle` tag
- is thread safe, this leakage no longer occurs.
- ``user_passes_test``, ``login_required`` and ``permission_required``
- --------------------------------------------------------------------
- ``django.contrib.auth.decorators`` provides the decorators
- ``login_required``, ``permission_required`` and
- ``user_passes_test``. Previously it was possible to use these
- decorators both on functions (where the first argument is 'request')
- and on methods (where the first argument is 'self', and the second
- argument is 'request'). Unfortunately, flaws were discovered in the
- code supporting this: it only works in limited circumstances, and
- produces errors that are very difficult to debug when it does not
- work.
- For this reason, the 'auto adapt' behavior has been removed, and if
- you are using these decorators on methods, you will need to manually
- apply :func:`django.utils.decorators.method_decorator` to convert the
- decorator to one that works with methods. For example, you would
- change code from this::
- class MyClass(object):
- @login_required
- def my_view(self, request):
- pass
- to this::
- from django.utils.decorators import method_decorator
- class MyClass(object):
- @method_decorator(login_required)
- def my_view(self, request):
- pass
- or::
- from django.utils.decorators import method_decorator
- login_required_m = method_decorator(login_required)
- class MyClass(object):
- @login_required_m
- def my_view(self, request):
- pass
- For those of you who've been following the development trunk, this
- change also applies to other decorators introduced since 1.1,
- including ``csrf_protect``, ``cache_control`` and anything created
- using ``decorator_from_middleware``.
- :ttag:`if` tag changes
- ----------------------
- Due to new features in the :ttag:`if` template tag, it no longer
- accepts 'and', 'or' and 'not' as valid **variable** names. Previously,
- these strings could be used as variable names. Now, the keyword status
- is always enforced, and template code such as ``{% if not %}`` or ``{%
- if and %}`` will throw a ``TemplateSyntaxError``. Also, ``in`` is a
- new keyword and so is not a valid variable name in this tag.
- ``LazyObject``
- --------------
- ``LazyObject`` is an undocumented-but-often-used utility class used for lazily
- wrapping other objects of unknown type.
- In Django 1.1 and earlier, it handled introspection in a non-standard way,
- depending on wrapped objects implementing a public method named
- ``get_all_members()``. Since this could easily lead to name clashes, it has been
- changed to use the standard Python introspection method, involving
- ``__members__`` and ``__dir__()``.
- If you used ``LazyObject`` in your own code
- and implemented the ``get_all_members()`` method for wrapped objects, you'll need
- to make a couple of changes:
- First, if your class does not have special requirements for introspection (i.e.,
- you have not implemented ``__getattr__()`` or other methods that allow for
- attributes not discoverable by normal mechanisms), you can simply remove the
- ``get_all_members()`` method. The default implementation on ``LazyObject`` will
- do the right thing.
- If you have more complex requirements for introspection, first rename the
- ``get_all_members()`` method to ``__dir__()``. This is the standard
- introspection method for Python 2.6 and above. If you require support for Python
- versions earlier than 2.6, add the following code to the class::
- __members__ = property(lambda self: self.__dir__())
- ``__dict__`` on model instances
- -------------------------------
- Historically, the ``__dict__`` attribute of a model instance has only contained
- attributes corresponding to the fields on a model.
- In order to support multiple database configurations, Django 1.2 has
- added a ``_state`` attribute to object instances. This attribute will
- appear in ``__dict__`` for a model instance. If your code relies on
- iterating over ``__dict__`` to obtain a list of fields, you must now
- be prepared to handle or filter out the ``_state`` attribute.
- Test runner exit status code
- ----------------------------
- The exit status code of the test runners (``tests/runtests.py`` and ``python
- manage.py test``) no longer represents the number of failed tests, because a
- failure of 256 or more tests resulted in a wrong exit status code. The exit
- status code for the test runner is now 0 for success (no failing tests) and 1
- for any number of test failures. If needed, the number of test failures can be
- found at the end of the test runner's output.
- Cookie encoding
- ---------------
- To fix bugs with cookies in Internet Explorer, Safari, and possibly
- other browsers, our encoding of cookie values was changed so that the
- comma and semicolon are treated as non-safe characters, and are
- therefore encoded as ``\054`` and ``\073`` respectively. This could
- produce backwards incompatibilities, especially if you are storing
- comma or semi-colon in cookies and have javascript code that parses
- and manipulates cookie values client-side.
- ``ModelForm.is_valid()`` and ``ModelForm.errors``
- -------------------------------------------------
- Much of the validation work for ModelForms has been moved down to the model
- level. As a result, the first time you call ``ModelForm.is_valid()``, access
- ``ModelForm.errors`` or otherwise trigger form validation, your model will be
- cleaned in-place. This conversion used to happen when the model was saved. If
- you need an unmodified instance of your model, you should pass a copy to the
- ``ModelForm`` constructor.
- ``BooleanField`` on MySQL
- --------------------------
- In previous versions of Django, a model's ``BooleanField`` under MySQL
- would return its value as either ``1`` or ``0``, instead of ``True``
- or ``False``; for most people this wasn't a problem because ``bool``
- is a subclass of ``int`` in Python. In Django 1.2, however,
- ``BooleanField`` on MySQL correctly returns a real ``bool``. The only
- time this should ever be an issue is if you were expecting the
- ``repr`` of a ``BooleanField`` to print ``1`` or ``0``.
- Changes to the interpretation of ``max_num`` in FormSets
- --------------------------------------------------------
- As part of enhancements made to the handling of FormSets, the default
- value and interpretation of the ``max_num`` parameter to the
- :ref:`django.forms.formsets.formset_factory() <formsets-max-num>` and
- :ref:`django.forms.models.modelformset_factory()
- <model-formsets-max-num>` functions has changed slightly. This
- change also affects the way the
- :attr:`~django.contrib.admin.InlineModelAdmin.max_num` argument is used for
- inline admin objects.
- Previously, the default value for ``max_num`` was ``0`` (zero).
- FormSets then used the boolean value of ``max_num`` to determine if a
- limit was to be imposed on the number of generated forms. The default
- value of ``0`` meant that there was no default limit on the number of
- forms in a FormSet.
- Starting with 1.2, the default value for ``max_num`` has been changed
- to ``None``, and FormSets will differentiate between a value of
- ``None`` and a value of ``0``. A value of ``None`` indicates that no
- limit on the number of forms is to be imposed; a value of ``0``
- indicates that a maximum of 0 forms should be imposed. This doesn't
- necessarily mean that no forms will be displayed -- see the
- :ref:`ModelFormSet documentation <model-formsets-max-num>` for more
- details.
- If you were manually specifying a value of ``0`` for ``max_num``, you
- will need to update your FormSet and/or admin definitions.
- .. seealso::
- :ref:`1.2-js-assisted-inlines`
- ``email_re``
- ------------
- An undocumented regular expression for validating email addresses has been moved
- from ``django.form.fields`` to ``django.core.validators``. You will need to
- update your imports if you are using it.
- .. _deprecated-features-1.2:
- Features deprecated in 1.2
- ==========================
- Finally, Django 1.2 deprecates some features from earlier releases.
- These features are still supported, but will be gradually phased out
- over the next few release cycles.
- Code taking advantage of any of the features below will raise a
- ``PendingDeprecationWarning`` in Django 1.2. This warning will be
- silent by default, but may be turned on using Python's :mod:`warnings`
- module, or by running Python with a ``-Wd`` or ``-Wall`` flag.
- In Django 1.3, these warnings will become a ``DeprecationWarning``,
- which is *not* silent. In Django 1.4 support for these features will
- be removed entirely.
- .. seealso::
- For more details, see the documentation :doc:`Django's release process
- </internals/release-process>` and our :doc:`deprecation timeline
- </internals/deprecation>`.`
- .. _specifying-databases:
- Specifying databases
- --------------------
- Prior to Django 1.2, Django used a number of settings to control
- access to a single database. Django 1.2 introduces support for
- multiple databases, and as a result the way you define database
- settings has changed.
- Any existing Django settings file will continue to work as expected
- until Django 1.4. Until then, old-style database settings will be
- automatically translated to the new-style format.
- In the old-style (pre 1.2) format, you had a number of ``DATABASE_``
- settings in your settings file. For example::
- DATABASE_NAME = 'test_db'
- DATABASE_ENGINE = 'postgresql_psycopg2'
- DATABASE_USER = 'myusername'
- DATABASE_PASSWORD = 's3krit'
- These settings are now in a dictionary named
- :setting:`DATABASES`. Each item in the dictionary corresponds to a
- single database connection, with the name ``'default'`` describing the
- default database connection. The setting names have also been
- shortened. The previous sample settings would now look like this::
- DATABASES = {
- 'default': {
- 'NAME': 'test_db',
- 'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'USER': 'myusername',
- 'PASSWORD': 's3krit',
- }
- }
- This affects the following settings:
- ========================================= ==========================
- Old setting New Setting
- ========================================= ==========================
- `DATABASE_ENGINE` :setting:`ENGINE <DATABASE-ENGINE>`
- `DATABASE_HOST` :setting:`HOST`
- `DATABASE_NAME` :setting:`NAME`
- `DATABASE_OPTIONS` :setting:`OPTIONS`
- `DATABASE_PASSWORD` :setting:`PASSWORD`
- `DATABASE_PORT` :setting:`PORT`
- `DATABASE_USER` :setting:`USER`
- `TEST_DATABASE_CHARSET` :setting:`TEST_CHARSET`
- `TEST_DATABASE_COLLATION` :setting:`TEST_COLLATION`
- `TEST_DATABASE_NAME` :setting:`TEST_NAME`
- ========================================= ==========================
- These changes are also required if you have manually created a database
- connection using ``DatabaseWrapper()`` from your database backend of choice.
- In addition to the change in structure, Django 1.2 removes the special
- handling for the built-in database backends. All database backends
- must now be specified by a fully qualified module name (i.e.,
- ``django.db.backends.postgresql_psycopg2``, rather than just
- ``postgresql_psycopg2``).
- ``postgresql`` database backend
- -------------------------------
- The ``psycopg1`` library has not been updated since October 2005. As a
- result, the ``postgresql`` database backend, which uses this library,
- has been deprecated.
- If you are currently using the ``postgresql`` backend, you should
- migrate to using the ``postgresql_psycopg2`` backend. To update your
- code, install the ``psycopg2`` library and change the
- :setting:`ENGINE <DATABASE-ENGINE>` setting to use
- ``django.db.backends.postgresql_psycopg2``.
- CSRF response-rewriting middleware
- ----------------------------------
- ``CsrfResponseMiddleware``, the middleware that automatically inserted
- CSRF tokens into ``POST`` forms in outgoing pages, has been deprecated
- in favor of a template tag method (see above), and will be removed
- completely in Django 1.4. ``CsrfMiddleware``, which includes the
- functionality of ``CsrfResponseMiddleware`` and
- ``CsrfViewMiddleware``, has likewise been deprecated.
- Also, the CSRF module has moved from contrib to core, and the old
- imports are deprecated, as described in the upgrading notes.
- .. admonition:: Documentation removed
- The upgrade notes have been removed in current Django docs. Please refer
- to the docs for Django 1.3 or older to find these instructions.
- ``SMTPConnection``
- ------------------
- The ``SMTPConnection`` class has been deprecated in favor of a generic
- email backend API. Old code that explicitly instantiated an instance
- of an SMTPConnection::
- from django.core.mail import SMTPConnection
- connection = SMTPConnection()
- messages = get_notification_email()
- connection.send_messages(messages)
- ...should now call :meth:`~django.core.mail.get_connection()` to
- instantiate a generic email connection::
- from django.core.mail import get_connection
- connection = get_connection()
- messages = get_notification_email()
- connection.send_messages(messages)
- Depending on the value of the :setting:`EMAIL_BACKEND` setting, this
- may not return an SMTP connection. If you explicitly require an SMTP
- connection with which to send email, you can explicitly request an
- SMTP connection::
- from django.core.mail import get_connection
- connection = get_connection('django.core.mail.backends.smtp.EmailBackend')
- messages = get_notification_email()
- connection.send_messages(messages)
- If your call to construct an instance of ``SMTPConnection`` required
- additional arguments, those arguments can be passed to the
- :meth:`~django.core.mail.get_connection()` call::
- connection = get_connection('django.core.mail.backends.smtp.EmailBackend', hostname='localhost', port=1234)
- User Messages API
- -----------------
- The API for storing messages in the user ``Message`` model (via
- ``user.message_set.create``) is now deprecated and will be removed in Django
- 1.4 according to the standard :doc:`release process </internals/release-process>`.
- To upgrade your code, you need to replace any instances of this::
- user.message_set.create('a message')
- ...with the following::
- from django.contrib import messages
- messages.add_message(request, messages.INFO, 'a message')
- Additionally, if you make use of the method, you need to replace the
- following::
- for message in user.get_and_delete_messages():
- ...
- ...with::
- from django.contrib import messages
- for message in messages.get_messages(request):
- ...
- For more information, see the full
- :doc:`messages documentation </ref/contrib/messages>`. You should begin to
- update your code to use the new API immediately.
- Date format helper functions
- ----------------------------
- ``django.utils.translation.get_date_formats()`` and
- ``django.utils.translation.get_partial_date_formats()`` have been deprecated
- in favor of the appropriate calls to ``django.utils.formats.get_format()``,
- which is locale-aware when :setting:`USE_L10N` is set to ``True``, and falls
- back to default settings if set to ``False``.
- To get the different date formats, instead of writing this::
- from django.utils.translation import get_date_formats
- date_format, datetime_format, time_format = get_date_formats()
- ...use::
- from django.utils import formats
- date_format = formats.get_format('DATE_FORMAT')
- datetime_format = formats.get_format('DATETIME_FORMAT')
- time_format = formats.get_format('TIME_FORMAT')
- Or, when directly formatting a date value::
- from django.utils import formats
- value_formatted = formats.date_format(value, 'DATETIME_FORMAT')
- The same applies to the globals found in ``django.forms.fields``:
- * ``DEFAULT_DATE_INPUT_FORMATS``
- * ``DEFAULT_TIME_INPUT_FORMATS``
- * ``DEFAULT_DATETIME_INPUT_FORMATS``
- Use ``django.utils.formats.get_format()`` to get the appropriate formats.
- Function-based test runners
- ---------------------------
- Django 1.2 changes the test runner tools to use a class-based
- approach. Old style function-based test runners will still work, but
- should be updated to use the new :ref:`class-based runners
- <topics-testing-test_runner>`.
- .. _1.2-updating-feeds:
- ``Feed`` in ``django.contrib.syndication.feeds``
- ------------------------------------------------
- The ``django.contrib.syndication.feeds.Feed`` class has been
- replaced by the :class:`django.contrib.syndication.views.Feed` class.
- The old ``feeds.Feed`` class is deprecated, and will be removed in
- Django 1.4.
- The new class has an almost identical API, but allows instances to be
- used as views. For example, consider the use of the old framework in
- the following :doc:`URLconf </topics/http/urls>`::
- from django.conf.urls.defaults import *
- from myproject.feeds import LatestEntries, LatestEntriesByCategory
- feeds = {
- 'latest': LatestEntries,
- 'categories': LatestEntriesByCategory,
- }
- urlpatterns = patterns('',
- # ...
- (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
- {'feed_dict': feeds}),
- # ...
- )
- Using the new Feed class, these feeds can be deployed directly as views::
- from django.conf.urls.defaults import *
- from myproject.feeds import LatestEntries, LatestEntriesByCategory
- urlpatterns = patterns('',
- # ...
- (r'^feeds/latest/$', LatestEntries()),
- (r'^feeds/categories/(?P<category_id>\d+)/$', LatestEntriesByCategory()),
- # ...
- )
- If you currently use the ``feed()`` view, the ``LatestEntries`` class would
- often not need to be modified apart from subclassing the new
- :class:`~django.contrib.syndication.views.Feed` class. The exception is if
- Django was automatically working out the name of the template to use to render
- the feed's description and title elements (if you were not specifying the
- ``title_template`` and ``description_template`` attributes). You should ensure
- that you always specify ``title_template`` and ``description_template``
- attributes, or provide ``item_title()`` and ``item_description()`` methods.
- However, ``LatestEntriesByCategory`` uses the ``get_object()`` method
- with the ``bits`` argument to specify a specific category to show. In
- the new :class:`~django.contrib.syndication.views.Feed` class,
- ``get_object()`` method takes a ``request`` and arguments from the
- URL, so it would look like this::
- from django.contrib.syndication.views import Feed
- from django.shortcuts import get_object_or_404
- from myproject.models import Category
- class LatestEntriesByCategory(Feed):
- def get_object(self, request, category_id):
- return get_object_or_404(Category, id=category_id)
- # ...
- Additionally, the ``get_feed()`` method on ``Feed`` classes now take
- different arguments, which may impact you if you use the ``Feed``
- classes directly. Instead of just taking an optional ``url`` argument,
- it now takes two arguments: the object returned by its own
- ``get_object()`` method, and the current ``request`` object.
- To take into account ``Feed`` classes not being initialized for each
- request, the ``__init__()`` method now takes no arguments by default.
- Previously it would have taken the ``slug`` from the URL and the
- ``request`` object.
- In accordance with `RSS best practices`_, RSS feeds will now include
- an ``atom:link`` element. You may need to update your tests to take
- this into account.
- For more information, see the full :doc:`syndication framework
- documentation </ref/contrib/syndication>`.
- .. _RSS best practices: http://www.rssboard.org/rss-profile
- Technical message IDs
- ---------------------
- Up to version 1.1 Django used technical message IDs
- to provide localizers the possibility to translate date and time formats. They
- were translatable :term:`translation strings <translation string>` that could
- be recognized because they were all upper case (for example
- :setting:`DATETIME_FORMAT`, :setting:`DATE_FORMAT`, :setting:`TIME_FORMAT`).
- They have been deprecated in favor of the new :ref:`Format localization
- <format-localization>` infrastructure that allows localizers to specify that
- information in a ``formats.py`` file in the corresponding
- ``django/conf/locale/<locale name>/`` directory.
- GeoDjango
- ---------
- To allow support for multiple databases, the GeoDjango database internals were
- changed substantially. The largest backwards-incompatible change is that
- the module ``django.contrib.gis.db.backend`` was renamed to
- :mod:`django.contrib.gis.db.backends`, where the full-fledged
- :ref:`spatial database backends <spatial-backends>` now exist. The
- following sections provide information on the most-popular APIs that
- were affected by these changes.
- ``SpatialBackend``
- ^^^^^^^^^^^^^^^^^^
- Prior to the creation of the separate spatial backends, the
- ``django.contrib.gis.db.backend.SpatialBackend`` object was
- provided as an abstraction to introspect on the capabilities of
- the spatial database. All of the attributes and routines provided by
- ``SpatialBackend`` are now a part of the ``ops`` attribute of the
- database backend.
- The old module ``django.contrib.gis.db.backend`` is still provided
- for backwards-compatibility access to a ``SpatialBackend`` object,
- which is just an alias to the ``ops`` module of the
- *default* spatial database connection.
- Users that were relying on undocumented modules and objects
- within ``django.contrib.gis.db.backend``, rather the abstractions
- provided by ``SpatialBackend``, are required to modify their code.
- For example, the following import which would work in 1.1 and
- below::
- from django.contrib.gis.db.backend.postgis import PostGISAdaptor
- Would need to be changed::
- from django.db import connection
- PostGISAdaptor = connection.ops.Adapter
- ``SpatialRefSys`` and ``GeometryColumns`` models
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- In previous versions of GeoDjango, :mod:`django.contrib.gis.db.models`
- had ``SpatialRefSys`` and ``GeometryColumns`` models for querying
- the OGC spatial metadata tables ``spatial_ref_sys`` and ``geometry_columns``,
- respectively.
- While these aliases are still provided, they are only for the
- *default* database connection and exist only if the default connection
- is using a supported spatial database backend.
- .. note::
- Because the table structure of the OGC spatial metadata tables
- differs across spatial databases, the ``SpatialRefSys`` and
- ``GeometryColumns`` models can no longer be associated with
- the ``gis`` application name. Thus, no models will be returned
- when using the ``get_models`` method in the following example::
- >>> from django.db.models import get_app, get_models
- >>> get_models(get_app('gis'))
- []
- To get the correct ``SpatialRefSys`` and ``GeometryColumns``
- for your spatial database use the methods provided by the spatial backend::
- >>> from django.db import connections
- >>> SpatialRefSys = connections['my_spatialite'].ops.spatial_ref_sys()
- >>> GeometryColumns = connections['my_postgis'].ops.geometry_columns()
- .. note::
- When using the models returned from the ``spatial_ref_sys()`` and
- ``geometry_columns()`` method, you'll still need to use the
- correct database alias when querying on the non-default connection.
- In other words, to ensure that the models in the example above
- use the correct database::
- sr_qs = SpatialRefSys.objects.using('my_spatialite').filter(...)
- gc_qs = GeometryColumns.objects.using('my_postgis').filter(...)
- Language code ``no``
- --------------------
- The currently used language code for Norwegian Bokmål ``no`` is being
- replaced by the more common language code ``nb``.
- Function-based template loaders
- -------------------------------
- Django 1.2 changes the template loading mechanism to use a class-based
- approach. Old style function-based template loaders will still work, but should
- be updated to use the new :ref:`class-based template loaders
- <topic-template-alternate-language>`.
|