diff -r 5ff1fc726848 -r c6bca38c1cbf parts/django/docs/releases/1.2.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parts/django/docs/releases/1.2.txt Sat Jan 08 11:20:57 2011 +0530 @@ -0,0 +1,1139 @@ +======================== +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 e-mail sending via `e-mail backends`_. + + * New :ref:`"smart" if template tag ` 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: http://djangoadvent.com/ + +Wherever possible these features have been introduced in a backwards-compatible +manner per :doc:`our API stability policy ` 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 +` and the list of :ref:`deprecated +features `. + +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 `, 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 +` 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 +`, and both model and form fields now accept configurable +lists of :doc:`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`. 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 +` 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 +` 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 ` 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. + +E-mail backends +--------------- + +You can now :ref:`configure the way that Django sends e-mail +`. Instead of using SMTP to send all e-mail, you +can now choose a configurable e-mail 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 e-mail backend that will allow +Django's standard :doc:`mail sending methods` to use +those facilities. + +This also makes it easier to debug mail sending. Django ships with +backend implementations that allow you to send e-mail to a +:ref:`file`, to the +:ref:`console`, or to +:ref:`memory`. You can even configure all +e-mail to be :ref:`thrown away`. + +.. _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 + +
{{ message }}
+ +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 ` 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`. + +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 ` 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 ` 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 +`. + +Syndication feeds as views +-------------------------- + +:doc:`Syndication feeds ` can now be used directly as +views in your :doc:`URLconf `. 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 ` +in 1.2 is support for multiple spatial databases. As a result, +the following :ref:`spatial database backends ` +are now included: + +* :mod:`django.contrib.gis.db.backends.postgis` +* :mod:`django.contrib.gis.db.backends.mysql` +* :mod:`django.contrib.gis.db.backends.oracle` +* :mod:`django.contrib.gis.db.backends.spatialite` + +GeoDjango now supports the rich capabilities added +in the `PostGIS 1.5 release `_. +New features include suppport for the the :ref:`geography type ` +and enabling of :ref:`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 ` was updated to use +thread-safe C library functions when available on the platform. + +The :ref:`GDAL interface ` 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 ` is now +included with Django's and is no longer +hosted separately at `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 +` 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 documentaton `. 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 :ref:`UPGRADE + INSTRUCTIONS ` to fix those templates. + + * ``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`. + +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`. + +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() ` and +:ref:`django.forms.models.modelformset_factory() +` functions has changed slightly. This +change also affects the way the ``max_num`` argument is :ref:`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 ` 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 `warnings +module`_, or by running Python with a ``-Wd`` or `-Wall` flag. + +.. _warnings module: http://docs.python.org/library/warnings.html + +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 + ` and our :doc:`deprecation timeline + `.` + +.. _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 + ========================================= ========================== + :setting:`DATABASE_ENGINE` :setting:`ENGINE` + :setting:`DATABASE_HOST` :setting:`HOST` + :setting:`DATABASE_NAME` :setting:`NAME` + :setting:`DATABASE_OPTIONS` :setting:`OPTIONS` + :setting:`DATABASE_PASSWORD` :setting:`PASSWORD` + :setting:`DATABASE_PORT` :setting:`PORT` + :setting:`DATABASE_USER` :setting:`USER` + :setting:`TEST_DATABASE_CHARSET` :setting:`TEST_CHARSET` + :setting:`TEST_DATABASE_COLLATION` :setting:`TEST_COLLATION` + :setting:`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:`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 :ref:`upgrading notes +`. + +``SMTPConnection`` +------------------ + +The ``SMTPConnection`` class has been deprecated in favor of a generic +e-mail 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 e-mail 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 e-mail, 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 `. + +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 `. 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 +`. + +.. _1.2-updating-feeds: + +``Feed`` in ``django.contrib.syndication.feeds`` +------------------------------------------------ + +The :class:`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 `:: + + from django.conf.urls.defaults import * + from myproject.feeds import LatestEntries, LatestEntriesByCategory + + feeds = { + 'latest': LatestEntries, + 'categories': LatestEntriesByCategory, + } + + urlpatterns = patterns('', + # ... + (r'^feeds/(?P.*)/$', '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\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 `. + +.. _RSS best practices: http://www.rssboard.org/rss-profile + +Technical message IDs +--------------------- + +Up to version 1.1 Django used :ref:`technical message IDs` +to provide localizers the possibility to translate date and time formats. They +were translatable :term:`translation strings ` that could +be recognized because they were all upper case (for example +``DATETIME_FORMAT``, ``DATE_FORMAT``, ``TIME_FORMAT``). They have been +deprecated in favor of the new :ref:`Format localization +` infrastructure that allows localizers to specify that +information in a ``formats.py`` file in the corresponding +``django/conf/locale//`` 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 ` 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``. +