============================================ Django 1.3 release notes - UNDER DEVELOPMENT ============================================ This page documents release notes for the as-yet-unreleased Django 1.3. As such, it's tentative and subject to change. It provides up-to-date information for those who are following trunk. Django 1.3 includes a number of nifty `new features`_, lots of bug fixes, some minor `backwards incompatible changes`_ and an easy upgrade path from Django 1.2. .. _new features: `What's new in Django 1.3`_ .. _backwards incompatible changes: backwards-incompatible-changes-1.3_ What's new in Django 1.3 ======================== Class-based views ~~~~~~~~~~~~~~~~~ Django 1.3 adds a framework that allows you to use a class as a view. This means you can compose a view out of a collection of methods that can be subclassed and overridden to provide common views of data without having to write too much code. Analogs of all the old function-based generic views have been provided, along with a completely generic view base class that can be used as the basis for reusable applications that can be easily extended. See :doc:`the documentation on Class-based Generic Views` for more details. There is also a document to help you :doc:`convert your function-based generic views to class-based views`. Logging ~~~~~~~ Django 1.3 adds framework-level support for Python's logging module. This means you can now easily configure and control logging as part of your Django project. A number of logging handlers and logging calls have been added to Django's own code as well -- most notably, the error emails sent on a HTTP 500 server error are now handled as a logging activity. See :doc:`the documentation on Django's logging interface ` for more details. Extended static files handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Django 1.3 ships with a new contrib app ``'django.contrib.staticfiles'`` to help developers handle the static media files (images, CSS, Javascript, etc.) that are needed to render a complete web page. In previous versions of Django, it was common to place static assets in :setting:`MEDIA_ROOT` along with user-uploaded files, and serve them both at :setting:`MEDIA_URL`. Part of the purpose of introducing the ``staticfiles`` app is to make it easier to keep static files separate from user-uploaded files. For this reason, you will probably want to make your :setting:`MEDIA_ROOT` and :setting:`MEDIA_URL` different from your :setting:`STATIC_ROOT` and :setting:`STATIC_URL`. You will need to arrange for serving of files in :setting:`MEDIA_ROOT` yourself; ``staticfiles`` does not deal with user-uploaded media at all. See the :doc:`reference documentation of the app ` for more details or learn how to :doc:`manage static files `. ``unittest2`` support ~~~~~~~~~~~~~~~~~~~~~ Python 2.7 introduced some major changes to the unittest library, adding some extremely useful features. To ensure that every Django project can benefit from these new features, Django ships with a copy of unittest2_, a copy of the Python 2.7 unittest library, backported for Python 2.4 compatibility. To access this library, Django provides the ``django.utils.unittest`` module alias. If you are using Python 2.7, or you have installed unittest2 locally, Django will map the alias to the installed version of the unittest library. Otherwise, Django will use it's own bundled version of unittest2. To use this alias, simply use:: from django.utils import unittest wherever you would have historically used:: import unittest If you want to continue to use the base unittest libary, you can -- you just won't get any of the nice new unittest2 features. .. _unittest2: http://pypi.python.org/pypi/unittest2 Transaction context managers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Users of Python 2.5 and above may now use :ref:`transaction management functions ` as `context managers`_. For example:: with transaction.autocommit(): # ... .. _context managers: http://docs.python.org/glossary.html#term-context-manager For more information, see :ref:`transaction-management-functions`. Configurable delete-cascade ~~~~~~~~~~~~~~~~~~~~~~~~~~~ :class:`~django.db.models.ForeignKey` and :class:`~django.db.models.OneToOneField` now accept an :attr:`~django.db.models.ForeignKey.on_delete` argument to customize behavior when the referenced object is deleted. Previously, deletes were always cascaded; available alternatives now include set null, set default, set to any value, protect, or do nothing. For more information, see the :attr:`~django.db.models.ForeignKey.on_delete` documentation. Contextual markers and comments for translatable strings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For translation strings with ambiguous meaning, you can now use the ``pgettext`` function to specify the context of the string. And if you just want to add some information for translators, you can also add special translator comments in the source. For more information, see :ref:`contextual-markers` and :ref:`translator-comments`. Everything else ~~~~~~~~~~~~~~~ Django :doc:`1.1 <1.1>` and :doc:`1.2 <1.2>` added lots of big ticket items to Django, like multiple-database support, model validation, and a session-based messages framework. However, this focus on big features came at the cost of lots of smaller features. To compensate for this, the focus of the Django 1.3 development process has been on adding lots of smaller, long standing feature requests. These include: * Improved tools for accessing and manipulating the current Site. * A :class:`~django.test.client.RequestFactory` for mocking requests in tests. * A new test assertion -- :meth:`~django.test.client.Client.assertNumQueries` -- making it easier to test the database activity associated with a view. * :ref:`Versioning `, :ref:`site-wide prefixing ` and :ref:`transformation ` has been added to the cache API. .. _backwards-incompatible-changes-1.3: Backwards-incompatible changes in 1.3 ===================================== PasswordInput default rendering behavior ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The :class:`~django.forms.PasswordInput` form widget, intended for use with form fields which represent passwords, accepts a boolean keyword argument ``render_value`` indicating whether to send its data back to the browser when displaying a submitted form with errors. Prior to Django 1.3, this argument defaulted to ``True``, meaning that the submitted password would be sent back to the browser as part of the form. Developers who wished to add a bit of additional security by excluding that value from the redisplayed form could instantiate a :class:`~django.forms.PasswordInput` passing ``render_value=False`` . Due to the sensitive nature of passwords, however, Django 1.3 takes this step automatically; the default value of ``render_value`` is now ``False``, and developers who want the password value returned to the browser on a submission with errors (the previous behavior) must now explicitly indicate this. For example:: class LoginForm(forms.Form): username = forms.CharField(max_length=100) password = forms.CharField(widget=forms.PasswordInput(render_value=True)) Clearable default widget for FileField ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Django 1.3 now includes a ``ClearableFileInput`` form widget in addition to ``FileInput``. ``ClearableFileInput`` renders with a checkbox to clear the field's value (if the field has a value and is not required); ``FileInput`` provided no means for clearing an existing file from a ``FileField``. ``ClearableFileInput`` is now the default widget for a ``FileField``, so existing forms including ``FileField`` without assigning a custom widget will need to account for the possible extra checkbox in the rendered form output. To return to the previous rendering (without the ability to clear the ``FileField``), use the ``FileInput`` widget in place of ``ClearableFileInput``. For instance, in a ``ModelForm`` for a hypothetical ``Document`` model with a ``FileField`` named ``document``:: from django import forms from myapp.models import Document class DocumentForm(forms.ModelForm): class Meta: model = Document widgets = {'document': forms.FileInput} New index on database session table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prior to Django 1.3, the database table used by the database backend for the :doc:`sessions ` app had no index on the ``expire_date`` column. As a result, date-based queries on the session table -- such as the query that is needed to purge old sessions -- would be very slow if there were lots of sessions. If you have an existing project that is using the database session backend, you don't have to do anything to accommodate this change. However, you may get a significant performance boost if you manually add the new index to the session table. The SQL that will add the index can be found by running the :djadmin:`sqlindexes` admin command:: python manage.py sqlindexes sessions No more naughty words ~~~~~~~~~~~~~~~~~~~~~ Django has historically provided (and enforced) a list of profanities. The :doc:`comments app ` has enforced this list of profanities, preventing people from submitting comments that contained one of those profanities. Unfortunately, the technique used to implement this profanities list was woefully naive, and prone to the `Scunthorpe problem`_. Fixing the built in filter to fix this problem would require significant effort, and since natural language processing isn't the normal domain of a web framework, we have "fixed" the problem by making the list of prohibited words an empty list. If you want to restore the old behavior, simply put a ``PROFANITIES_LIST`` setting in your settings file that includes the words that you want to prohibit (see the `commit that implemented this change`_ if you want to see the list of words that was historically prohibited). However, if avoiding profanities is important to you, you would be well advised to seek out a better, less naive approach to the problem. .. _Scunthorpe problem: http://en.wikipedia.org/wiki/Scunthorpe_problem .. _commit that implemented this change: http://code.djangoproject.com/changeset/13996 Localflavor changes ~~~~~~~~~~~~~~~~~~~ Django 1.3 introduces the following backwards-incompatible changes to local flavors: * Indonesia (id) -- The province "Nanggroe Aceh Darussalam (NAD)" has been removed from the province list in favor of the new official designation "Aceh (ACE)". FormSet updates ~~~~~~~~~~~~~~~ In Django 1.3 ``FormSet`` creation behavior is modified slightly. Historically the class didn't make a distinction between not being passed data and being passed empty dictionary. This was inconsistent with behavior in other parts of the framework. Starting with 1.3 if you pass in empty dictionary the ``FormSet`` will raise a ``ValidationError``. For example with a ``FormSet``:: >>> class ArticleForm(Form): ... title = CharField() ... pub_date = DateField() >>> ArticleFormSet = formset_factory(ArticleForm) the following code will raise a ``ValidationError``:: >>> ArticleFormSet({}) Traceback (most recent call last): ... ValidationError: [u'ManagementForm data is missing or has been tampered with'] if you need to instantiate an empty ``FormSet``, don't pass in the data or use ``None``:: >>> formset = ArticleFormSet() >>> formset = ArticleFormSet(data=None) .. _deprecated-features-1.3: Features deprecated in 1.3 ========================== Django 1.3 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.3. 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.4, these warnings will become a ``DeprecationWarning``, which is *not* silent. In Django 1.5 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 `. ``mod_python`` support ~~~~~~~~~~~~~~~~~~~~~~ The ``mod_python`` library has not had a release since 2007 or a commit since 2008. The Apache Foundation board voted to remove ``mod_python`` from the set of active projects in its version control repositories, and its lead developer has shifted all of his efforts toward the lighter, slimmer, more stable, and more flexible ``mod_wsgi`` backend. If you are currently using the ``mod_python`` request handler, it is strongly encouraged you redeploy your Django instances using :doc:`mod_wsgi `. Function-based generic views ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As a result of the introduction of class-based generic views, the function-based generic views provided by Django have been deprecated. The following modules and the views they contain have been deprecated: * :mod:`django.views.generic.create_update` * :mod:`django.views.generic.date_based` * :mod:`django.views.generic.list_detail` * :mod:`django.views.generic.simple` Test client response ``template`` attribute ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Django's :ref:`test client ` returns :class:`~django.test.client.Response` objects annotated with extra testing information. In Django versions prior to 1.3, this included a :attr:`~django.test.client.Response.template` attribute containing information about templates rendered in generating the response: either None, a single :class:`~django.template.Template` object, or a list of :class:`~django.template.Template` objects. This inconsistency in return values (sometimes a list, sometimes not) made the attribute difficult to work with. In Django 1.3 the :attr:`~django.test.client.Response.template` attribute is deprecated in favor of a new :attr:`~django.test.client.Response.templates` attribute, which is always a list, even if it has only a single element or no elements. ``DjangoTestRunner`` ~~~~~~~~~~~~~~~~~~~~ As a result of the introduction of support for unittest2, the features of :class:`django.test.simple.DjangoTestRunner` (including fail-fast and Ctrl-C test termination) have been made redundant. In view of this redundancy, :class:`~django.test.simple.DjangoTestRunner` has been turned into an empty placeholder class, and will be removed entirely in Django 1.5. Changes to :ttag:`url` and :ttag:`ssi` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Most template tags will allow you to pass in either constants or variables as arguments -- for example:: {% extends "base.html" %} allows you to specify a base template as a constant, but if you have a context variable ``templ`` that contains the value ``base.html``:: {% extends templ %} is also legal. However, due to an accident of history, the :ttag:`url` and :ttag:`ssi` are different. These tags use the second, quoteless syntax, but interpret the argument as a constant. This means it isn't possible to use a context variable as the target of a :ttag:`url` and :ttag:`ssi` tag. Django 1.3 marks the start of the process to correct this historical accident. Django 1.3 adds a new template library -- ``future`` -- that provides alternate implementations of the :ttag:`url` and :ttag:`ssi` template tags. This ``future`` library implement behavior that makes the handling of the first argument consistent with the handling of all other variables. So, an existing template that contains:: {% url sample %} should be replaced with:: {% load url from future %} {% url 'sample' %} The tags implementing the old behavior have been deprecated, and in Django 1.5, the old behavior will be replaced with the new behavior. To ensure compatibility with future versions of Django, existing templates should be modified to use the new ``future`` libraries and syntax.