| ============================== |
| Django 1.4 alpha release notes |
| ============================== |
| |
| December 22, 2011. |
| |
| Welcome to Django 1.4 alpha! |
| |
| This is the first in a series of preview/development releases leading up to |
| the eventual release of Django 1.4, scheduled for March 2012. This release is |
| primarily targeted at developers who are interested in trying out new features |
| and testing the Django codebase to help identify and resolve bugs prior to the |
| final 1.4 release. |
| |
| As such, this release is *not* intended for production use, and any such use |
| is discouraged. |
| |
| Django 1.4 alpha includes various `new features`_ and some minor `backwards |
| incompatible changes`_. There are also some features that have been dropped, |
| which are detailed in :doc:`our deprecation plan </internals/deprecation>`, |
| and we've `begun the deprecation process for some features`_. |
| |
| .. _new features: `What's new in Django 1.4`_ |
| .. _backwards incompatible changes: `Backwards incompatible changes in 1.4`_ |
| .. _begun the deprecation process for some features: `Features deprecated in 1.4`_ |
| |
| Python compatibility |
| ==================== |
| |
| While not a new feature, it's important to note that Django 1.4 introduces the |
| second shift in our Python compatibility policy since Django's initial public |
| debut. Django 1.2 dropped support for Python 2.3; now Django 1.4 drops support |
| for Python 2.4. As such, the minimum Python version required for Django is now |
| 2.5, and Django is tested and supported on Python 2.5, 2.6 and 2.7. |
| |
| This change should affect only a small number of Django users, as most |
| operating-system vendors today are shipping Python 2.5 or newer as their default |
| version. If you're still using Python 2.4, however, you'll need to stick to |
| Django 1.3 until you can upgrade; per :doc:`our support policy |
| </internals/release-process>`, Django 1.3 will continue to receive security |
| support until the release of Django 1.5. |
| |
| Django does not support Python 3.x at this time. A document outlining our full |
| timeline for deprecating Python 2.x and moving to Python 3.x will be published |
| before the release of Django 1.4. |
| |
| What's new in Django 1.4 |
| ======================== |
| |
| Support for in-browser testing frameworks |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django 1.4 supports integration with in-browser testing frameworks like |
| Selenium_. The new :class:`django.test.LiveServerTestCase` base class lets you |
| test the interactions between your site's front and back ends more |
| comprehensively. See the |
| :class:`documentation<django.test.LiveServerTestCase>` for more details and |
| concrete examples. |
| |
| .. _Selenium: http://seleniumhq.org/ |
| |
| ``SELECT FOR UPDATE`` support |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django 1.4 now includes a :meth:`QuerySet.select_for_update() |
| <django.db.models.query.QuerySet.select_for_update>` method which generates a |
| ``SELECT ... FOR UPDATE`` SQL query. This will lock rows until the end of the |
| transaction, meaning that other transactions cannot modify or delete rows |
| matched by a ``FOR UPDATE`` query. |
| |
| For more details, see the documentation for |
| :meth:`~django.db.models.query.QuerySet.select_for_update`. |
| |
| ``Model.objects.bulk_create`` in the ORM |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This method allows for more efficient creation of multiple objects in the ORM. |
| It can provide significant performance increases if you have many objects. |
| Django makes use of this internally, meaning some operations (such as database |
| setup for test suites) have seen a performance benefit as a result. |
| |
| See the :meth:`~django.db.models.query.QuerySet.bulk_create` docs for more |
| information. |
| |
| ``QuerySet.prefetch_related`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Similar to :meth:`~django.db.models.query.QuerySet.select_related` but with a |
| different strategy and broader scope, |
| :meth:`~django.db.models.query.QuerySet.prefetch_related` has been added to |
| :class:`~django.db.models.query.QuerySet`. This method returns a new |
| ``QuerySet`` that will prefetch each of the specified related lookups in a |
| single batch as soon as the query begins to be evaluated. Unlike |
| ``select_related``, it does the joins in Python, not in the database, and |
| supports many-to-many relationships, |
| :class:`~django.contrib.contenttypes.generic.GenericForeignKey` and more. This |
| allows you to fix a very common performance problem in which your code ends up |
| doing O(n) database queries (or worse) if objects on your primary ``QuerySet`` |
| each have many related objects that you also need. |
| |
| Improved password hashing |
| ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django's auth system (``django.contrib.auth``) stores passwords using a one-way |
| algorithm. Django 1.3 uses the SHA1_ algorithm, but increasing processor speeds |
| and theoretical attacks have revealed that SHA1 isn't as secure as we'd like. |
| Thus, Django 1.4 introduces a new password storage system: by default Django now |
| uses the PBKDF2_ algorithm (as recommended by NIST_). You can also easily choose |
| a different algorithm (including the popular bcrypt_ algorithm). For more |
| details, see :ref:`auth_password_storage`. |
| |
| .. _sha1: http://en.wikipedia.org/wiki/SHA1 |
| .. _pbkdf2: http://en.wikipedia.org/wiki/PBKDF2 |
| .. _nist: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf |
| .. _bcrypt: http://en.wikipedia.org/wiki/Bcrypt |
| |
| |
| HTML5 Doctype |
| ~~~~~~~~~~~~~ |
| |
| We've switched the admin and other bundled templates to use the HTML5 |
| doctype. While Django will be careful to maintain compatibility with older |
| browsers, this change means that you can use any HTML5 features you need in |
| admin pages without having to lose HTML validity or override the provided |
| templates to change the doctype. |
| |
| List filters in admin interface |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Prior to Django 1.4, the :mod:`~django.contrib.admin` app allowed you to specify |
| change list filters by specifying a field lookup, but didn't allow you to create |
| custom filters. This has been rectified with a simple API (previously used |
| internally and known as "FilterSpec"). For more details, see the documentation |
| for :attr:`~django.contrib.admin.ModelAdmin.list_filter`. |
| |
| Multiple sort in admin interface |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The admin change list now supports sorting on multiple columns. It respects all |
| elements of the :attr:`~django.contrib.admin.ModelAdmin.ordering` attribute, and |
| sorting on multiple columns by clicking on headers is designed to mimic the |
| behavior of desktop GUIs. The |
| :meth:`~django.contrib.admin.ModelAdmin.get_ordering` method for specifying the |
| ordering dynamically (e.g. depending on the request) has also been added. |
| |
| New ``ModelAdmin`` methods |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| A new :meth:`~django.contrib.admin.ModelAdmin.save_related` method was added to |
| :mod:`~django.contrib.admin.ModelAdmin` to ease customization of how |
| related objects are saved in the admin. |
| |
| Two other new methods, |
| :meth:`~django.contrib.admin.ModelAdmin.get_list_display` and |
| :meth:`~django.contrib.admin.ModelAdmin.get_list_display_links` |
| were added to :class:`~django.contrib.admin.ModelAdmin` to enable the dynamic |
| customization of fields and links displayed on the admin change list. |
| |
| Admin inlines respect user permissions |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Admin inlines will now only allow those actions for which the user has |
| permission. For ``ManyToMany`` relationships with an auto-created intermediate |
| model (which does not have its own permissions), the change permission for the |
| related model determines if the user has the permission to add, change or |
| delete relationships. |
| |
| Tools for cryptographic signing |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django 1.4 adds both a low-level API for signing values and a high-level API |
| for setting and reading signed cookies, one of the most common uses of |
| signing in Web applications. |
| |
| See the :doc:`cryptographic signing </topics/signing>` docs for more |
| information. |
| |
| Cookie-based session backend |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django 1.4 introduces a new cookie-based backend for the session framework |
| which uses the tools for :doc:`cryptographic signing </topics/signing>` to |
| store the session data in the client's browser. |
| |
| See the :ref:`cookie-based session backend <cookie-session-backend>` docs for |
| more information. |
| |
| New form wizard |
| ~~~~~~~~~~~~~~~ |
| |
| The previous ``FormWizard`` from the formtools contrib app has been |
| replaced with a new implementation based on the class-based views |
| introduced in Django 1.3. It features a pluggable storage API and doesn't |
| require the wizard to pass around hidden fields for every previous step. |
| |
| Django 1.4 ships with a session-based storage backend and a cookie-based |
| storage backend. The latter uses the tools for |
| :doc:`cryptographic signing </topics/signing>` also introduced in |
| Django 1.4 to store the wizard's state in the user's cookies. |
| |
| See the :doc:`form wizard </ref/contrib/formtools/form-wizard>` docs for |
| more information. |
| |
| ``reverse_lazy`` |
| ~~~~~~~~~~~~~~~~ |
| |
| A lazily evaluated version of :func:`django.core.urlresolvers.reverse` was |
| added to allow using URL reversals before the project's URLConf gets loaded. |
| |
| Translating URL patterns |
| ~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django 1.4 gained the ability to look for a language prefix in the URL pattern |
| when using the new :func:`~django.conf.urls.i18n.i18n_patterns` helper function. |
| Additionally, it's now possible to define translatable URL patterns using |
| :func:`~django.utils.translation.ugettext_lazy`. See |
| :ref:`url-internationalization` for more information about the language prefix |
| and how to internationalize URL patterns. |
| |
| Contextual translation support for ``{% trans %}`` and ``{% blocktrans %}`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The :ref:`contextual translation<contextual-markers>` support introduced in |
| Django 1.3 via the ``pgettext`` function has been extended to the |
| :ttag:`trans` and :ttag:`blocktrans` template tags using the new ``context`` |
| keyword. |
| |
| Customizable ``SingleObjectMixin`` URLConf kwargs |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Two new attributes, |
| :attr:`pk_url_kwarg<django.views.generic.detail.SingleObjectMixin.pk_url_kwarg>` |
| and |
| :attr:`slug_url_kwarg<django.views.generic.detail.SingleObjectMixin.slug_url_kwarg>`, |
| have been added to :class:`~django.views.generic.detail.SingleObjectMixin` to |
| enable the customization of URLConf keyword arguments used for single |
| object generic views. |
| |
| Assignment template tags |
| ~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| A new :ref:`assignment_tag<howto-custom-template-tags-assignment-tags>` helper |
| function was added to ``template.Library`` to ease the creation of template |
| tags that store data in a specified context variable. |
| |
| ``*args`` and ``**kwargs`` support for template tag helper functions |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The :ref:`simple_tag<howto-custom-template-tags-simple-tags>`, |
| :ref:`inclusion_tag <howto-custom-template-tags-inclusion-tags>` and |
| newly introduced |
| :ref:`assignment_tag<howto-custom-template-tags-assignment-tags>` template |
| helper functions may now accept any number of positional or keyword arguments. |
| For example: |
| |
| .. code-block:: python |
| |
| @register.simple_tag |
| def my_tag(a, b, *args, **kwargs): |
| warning = kwargs['warning'] |
| profile = kwargs['profile'] |
| ... |
| return ... |
| |
| Then in the template any number of arguments may be passed to the template tag. |
| For example: |
| |
| .. code-block:: html+django |
| |
| {% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %} |
| |
| No wrapping of exceptions in ``TEMPLATE_DEBUG`` mode |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| In previous versions of Django, whenever the :setting:`TEMPLATE_DEBUG` setting |
| was ``True``, any exception raised during template rendering (even exceptions |
| unrelated to template syntax) were wrapped in ``TemplateSyntaxError`` and |
| re-raised. This was done in order to provide detailed template source location |
| information in the debug 500 page. |
| |
| In Django 1.4, exceptions are no longer wrapped. Instead, the original |
| exception is annotated with the source information. This means that catching |
| exceptions from template rendering is now consistent regardless of the value of |
| :setting:`TEMPLATE_DEBUG`, and there's no need to catch and unwrap |
| ``TemplateSyntaxError`` in order to catch other errors. |
| |
| ``truncatechars`` template filter |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Added a filter which truncates a string to be no longer than the specified |
| number of characters. Truncated strings end with a translatable ellipsis |
| sequence ("..."). See the documentation for :tfilter:`truncatechars` for |
| more details. |
| |
| ``static`` template tag |
| ~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The :mod:`staticfiles<django.contrib.staticfiles>` contrib app has a new |
| :ttag:`static<staticfiles-static>` template tag to refer to files saved with |
| the :setting:`STATICFILES_STORAGE` storage backend. It uses the storage |
| backend's ``url`` method and therefore supports advanced features such as |
| :ref:`serving files from a cloud service<staticfiles-from-cdn>`. |
| |
| ``CachedStaticFilesStorage`` storage backend |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| In addition to the `static template tag`_, the |
| :mod:`staticfiles<django.contrib.staticfiles>` contrib app now has a |
| :class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage` backend |
| which caches the files it saves (when running the :djadmin:`collectstatic` |
| management command) by appending the MD5 hash of the file's content to the |
| filename. For example, the file ``css/styles.css`` would also be saved as |
| ``css/styles.55e7cbb9ba48.css`` |
| |
| See the :class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage` |
| docs for more information. |
| |
| Simple clickjacking protection |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| We've added a middleware to provide easy protection against `clickjacking |
| <http://en.wikipedia.org/wiki/Clickjacking>`_ using the ``X-Frame-Options`` |
| header. It's not enabled by default for backwards compatibility reasons, but |
| you'll almost certainly want to :doc:`enable it </ref/clickjacking/>` to help |
| plug that security hole for browsers that support the header. |
| |
| CSRF improvements |
| ~~~~~~~~~~~~~~~~~ |
| |
| We've made various improvements to our CSRF features, including the |
| :func:`~django.views.decorators.csrf.ensure_csrf_cookie` decorator which can |
| help with AJAX heavy sites, protection for PUT and DELETE requests, and the |
| :setting:`CSRF_COOKIE_SECURE` and :setting:`CSRF_COOKIE_PATH` settings which can |
| improve the security and usefulness of the CSRF protection. See the :doc:`CSRF |
| docs </ref/contrib/csrf>` for more information. |
| |
| Error report filtering |
| ~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Two new function decorators, :func:`sensitive_variables` and |
| :func:`sensitive_post_parameters`, were added to allow designating the |
| local variables and POST parameters which may contain sensitive |
| information and should be filtered out of error reports. |
| |
| All POST parameters are now systematically filtered out of error reports for |
| certain views (``login``, ``password_reset_confirm``, ``password_change``, and |
| ``add_view`` in :mod:`django.contrib.auth.views`, as well as |
| ``user_change_password`` in the admin app) to prevent the leaking of sensitive |
| information such as user passwords. |
| |
| You may override or customize the default filtering by writing a :ref:`custom |
| filter<custom-error-reports>`. For more information see the docs on |
| :ref:`Filtering error reports<filtering-error-reports>`. |
| |
| Extended IPv6 support |
| ~~~~~~~~~~~~~~~~~~~~~ |
| |
| The previously added support for IPv6 addresses when using the runserver |
| management command in Django 1.3 has now been further extended by adding |
| a :class:`~django.db.models.GenericIPAddressField` model field, |
| a :class:`~django.forms.GenericIPAddressField` form field and |
| the validators :data:`~django.core.validators.validate_ipv46_address` and |
| :data:`~django.core.validators.validate_ipv6_address` |
| |
| Updated default project layout and ``manage.py`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django 1.4 ships with an updated default project layout and ``manage.py`` file |
| for the :djadmin:`startproject` management command. These fix some issues with |
| the previous ``manage.py`` handling of Python import paths that caused double |
| imports, trouble moving from development to deployment, and other |
| difficult-to-debug path issues. |
| |
| The previous ``manage.py`` called functions that are now deprecated, and thus |
| projects upgrading to Django 1.4 should update their ``manage.py``. (The |
| old-style ``manage.py`` will continue to work as before until Django 1.6; in |
| 1.5 it will raise ``DeprecationWarning``). |
| |
| The new recommended ``manage.py`` file should look like this:: |
| |
| #!/usr/bin/env python |
| import os, sys |
| |
| if __name__ == "__main__": |
| os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings") |
| |
| from django.core.management import execute_from_command_line |
| |
| execute_from_command_line(sys.argv) |
| |
| ``{{ project_name }}`` should be replaced with the Python package name of the |
| actual project. |
| |
| If settings, URLconfs, and apps within the project are imported or referenced |
| using the project name prefix (e.g. ``myproject.settings``, ``ROOT_URLCONF = |
| "myproject.urls"``, etc), the new ``manage.py`` will need to be moved one |
| directory up, so it is outside the project package rather than adjacent to |
| ``settings.py`` and ``urls.py``. |
| |
| For instance, with the following layout:: |
| |
| manage.py |
| mysite/ |
| __init__.py |
| settings.py |
| urls.py |
| myapp/ |
| __init__.py |
| models.py |
| |
| You could import ``mysite.settings``, ``mysite.urls``, and ``mysite.myapp``, |
| but not ``settings``, ``urls``, or ``myapp`` as top-level modules. |
| |
| Anything imported as a top-level module can be placed adjacent to the new |
| ``manage.py``. For instance, to decouple "myapp" from the project module and |
| import it as just ``myapp``, place it outside the ``mysite/`` directory:: |
| |
| manage.py |
| myapp/ |
| __init__.py |
| models.py |
| mysite/ |
| __init__.py |
| settings.py |
| urls.py |
| |
| If the same code is imported inconsistently (some places with the project |
| prefix, some places without it), the imports will need to be cleaned up when |
| switching to the new ``manage.py``. |
| |
| Improved WSGI support |
| ~~~~~~~~~~~~~~~~~~~~~ |
| |
| The :djadmin:`startproject` management command now adds a :file:`wsgi.py` |
| module to the initial project layout, containing a simple WSGI application that |
| can be used for :doc:`deploying with WSGI app |
| servers</howto/deployment/wsgi/index>`. |
| |
| The :djadmin:`built-in development server<runserver>` now supports using an |
| externally-defined WSGI callable, so as to make it possible to run runserver |
| with the same WSGI configuration that is used for deployment. A new |
| :setting:`WSGI_APPLICATION` setting is available to configure which WSGI |
| callable :djadmin:`runserver` uses. |
| |
| (The :djadmin:`runfcgi` management command also internally wraps the WSGI |
| callable configured via :setting:`WSGI_APPLICATION`.) |
| |
| Custom project and app templates |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The :djadmin:`startapp` and :djadmin:`startproject` management commands |
| got a ``--template`` option for specifying a path or URL to a custom app or |
| project template. |
| |
| For example, Django will use the ``/path/to/my_project_template`` directory |
| when running the following command:: |
| |
| django-admin.py startproject --template=/path/to/my_project_template myproject |
| |
| You can also now provide a destination directory as the second |
| argument to both :djadmin:`startapp` and :djadmin:`startproject`:: |
| |
| django-admin.py startapp myapp /path/to/new/app |
| django-admin.py startproject myproject /path/to/new/project |
| |
| For more information, see the :djadmin:`startapp` and :djadmin:`startproject` |
| documentation. |
| |
| Support for time zones |
| ~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django 1.4 adds :ref:`support for time zones <time-zones>`. When it's enabled, |
| Django stores date and time information in UTC in the database, uses time |
| zone-aware datetime objects internally, and translates them to the end user's |
| time zone in templates and forms. |
| |
| Reasons for using this feature include: |
| |
| - Customizing date and time display for users around the world. |
| - Storing datetimes in UTC for database portability and interoperability. |
| (This argument doesn't apply to PostgreSQL, because it already stores |
| timestamps with time zone information in Django 1.3.) |
| - Avoiding data corruption problems around DST transitions. |
| |
| Time zone support is enabled by default in new projects created with |
| :djadmin:`startproject`. If you want to use this feature in an existing |
| project, there is a :ref:`migration guide <time-zones-migration-guide>`. |
| |
| Minor features |
| ~~~~~~~~~~~~~~ |
| |
| Django 1.4 also includes several smaller improvements worth noting: |
| |
| * A more usable stacktrace in the technical 500 page: frames in the |
| stack trace which reference Django's code are dimmed out, while |
| frames in user code are slightly emphasized. This change makes it |
| easier to scan a stacktrace for issues in user code. |
| |
| * :doc:`Tablespace support </topics/db/tablespaces>` in PostgreSQL. |
| |
| * Customizable names for :meth:`~django.template.Library.simple_tag`. |
| |
| * In the documentation, a helpful :doc:`security overview </topics/security>` |
| page. |
| |
| * The ``django.contrib.auth.models.check_password`` function has been moved |
| to the ``django.contrib.auth.utils`` module. Importing it from the old |
| location will still work, but you should update your imports. |
| |
| * The :djadmin:`collectstatic` management command gained a ``--clear`` option |
| to delete all files at the destination before copying or linking the static |
| files. |
| |
| * It is now possible to load fixtures containing forward references when using |
| MySQL with the InnoDB database engine. |
| |
| * A new 403 response handler has been added as |
| ``'django.views.defaults.permission_denied'``. You can set your own handler by |
| setting the value of :data:`django.conf.urls.handler403`. See the |
| documentation about :ref:`the 403 (HTTP Forbidden) view<http_forbidden_view>` |
| for more information. |
| |
| * The :ttag:`trans` template tag now takes an optional ``as`` argument to |
| be able to retrieve a translation string without displaying it but setting |
| a template context variable instead. |
| |
| * The :ttag:`if` template tag now supports ``{% elif %}`` clauses. |
| |
| * A new plain text version of the HTTP 500 status code internal error page |
| served when :setting:`DEBUG` is ``True`` is now sent to the client when |
| Django detects that the request has originated in JavaScript code |
| (:meth:`~django.http.HttpRequest.is_ajax` is used for this). |
| |
| Similarly to its HTML counterpart, it contains a collection of different |
| pieces of information about the state of the web application. |
| |
| This should make it easier to read when debugging interaction with |
| client-side Javascript code. |
| |
| * Added the :djadminopt:`--no-location` option to the :djadmin:`makemessages` |
| command. |
| |
| * Changed the ``locmem`` cache backend to use |
| ``pickle.HIGHEST_PROTOCOL`` for better compatibility with the other |
| cache backends. |
| |
| * Added support in the ORM for generating ``SELECT`` queries containing |
| ``DISTINCT ON``. |
| |
| The ``distinct()`` ``QuerySet`` method now accepts an optional list of model |
| field names. If specified, then the ``DISTINCT`` statement is limited to these |
| fields. This is only supported in PostgreSQL. |
| |
| For more details, see the documentation for |
| :meth:`~django.db.models.query.QuerySet.distinct`. |
| |
| Backwards incompatible changes in 1.4 |
| ===================================== |
| |
| django.contrib.admin |
| ~~~~~~~~~~~~~~~~~~~~ |
| |
| The included administration app ``django.contrib.admin`` has for a long time |
| shipped with a default set of static files such as JavaScript, images and |
| stylesheets. Django 1.3 added a new contrib app ``django.contrib.staticfiles`` |
| to handle such files in a generic way and defined conventions for static |
| files included in apps. |
| |
| Starting in Django 1.4 the admin's static files also follow this |
| convention to make it easier to deploy the included files. In previous |
| versions of Django, it was also common to define an ``ADMIN_MEDIA_PREFIX`` |
| setting to point to the URL where the admin's static files are served by a |
| web server. This setting has now been deprecated and replaced by the more |
| general setting :setting:`STATIC_URL`. Django will now expect to find the |
| admin static files under the URL ``<STATIC_URL>/admin/``. |
| |
| If you've previously used a URL path for ``ADMIN_MEDIA_PREFIX`` (e.g. |
| ``/media/``) simply make sure :setting:`STATIC_URL` and :setting:`STATIC_ROOT` |
| are configured and your web server serves the files correctly. The development |
| server continues to serve the admin files just like before. Don't hesitate to |
| consult the :doc:`static files howto </howto/static-files/index>` for further |
| details. |
| |
| In case your ``ADMIN_MEDIA_PREFIX`` is set to an specific domain (e.g. |
| ``http://media.example.com/admin/``) make sure to also set your |
| :setting:`STATIC_URL` setting to the correct URL, for example |
| ``http://media.example.com/``. |
| |
| .. warning:: |
| |
| If you're implicitly relying on the path of the admin static files on |
| your server's file system when you deploy your site, you have to update |
| that path. The files were moved from :file:`django/contrib/admin/media/` |
| to :file:`django/contrib/admin/static/admin/`. |
| |
| Supported browsers for the admin |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django hasn't had a clear policy on which browsers are supported for using the |
| admin app. Django's new policy formalizes existing practices: `YUI's A-grade`_ |
| browsers should provide a fully-functional admin experience, with the notable |
| exception of IE6, which is no longer supported. |
| |
| Released over ten years ago, IE6 imposes many limitations on modern web |
| development. The practical implications of this policy are that contributors |
| are free to improve the admin without consideration for these limitations. |
| |
| This new policy **has no impact** on development outside of the admin. Users of |
| Django are free to develop webapps compatible with any range of browsers. |
| |
| .. _YUI's A-grade: http://yuilibrary.com/yui/docs/tutorials/gbs/ |
| |
| Removed admin icons |
| ~~~~~~~~~~~~~~~~~~~ |
| |
| As part of an effort to improve the performance and usability of the admin's |
| changelist sorting interface and of the admin's :attr:`horizontal |
| <django.contrib.admin.ModelAdmin.filter_horizontal>` and :attr:`vertical |
| <django.contrib.admin.ModelAdmin.filter_vertical>` "filter" widgets, some icon |
| files were removed and grouped into two sprite files. |
| |
| Specifically: ``selector-add.gif``, ``selector-addall.gif``, |
| ``selector-remove.gif``, ``selector-removeall.gif``, |
| ``selector_stacked-add.gif`` and ``selector_stacked-remove.gif`` were |
| combined into ``selector-icons.gif``; and ``arrow-up.gif`` and |
| ``arrow-down.gif`` were combined into ``sorting-icons.gif``. |
| |
| If you used those icons to customize the admin then you will want to replace |
| them with your own icons or retrieve them from a previous release. |
| |
| CSS class names in admin forms |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| To avoid conflicts with other common CSS class names (e.g. "button"), a prefix |
| "field-" has been added to all CSS class names automatically generated from the |
| form field names in the main admin forms, stacked inline forms and tabular |
| inline cells. You will need to take that prefix into account in your custom |
| style sheets or javascript files if you previously used plain field names as |
| selectors for custom styles or javascript transformations. |
| |
| Compatibility with old signed data |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django 1.3 changed the cryptographic signing mechanisms used in a number of |
| places in Django. While Django 1.3 kept fallbacks that would accept hashes |
| produced by the previous methods, these fallbacks are removed in Django 1.4. |
| |
| So, if you upgrade to Django 1.4 directly from 1.2 or earlier, you may |
| lose/invalidate certain pieces of data that have been cryptographically signed |
| using an old method. To avoid this, use Django 1.3 first for a period of time |
| to allow the signed data to expire naturally. The affected parts are detailed |
| below, with 1) the consequences of ignoring this advice and 2) the amount of |
| time you need to run Django 1.3 for the data to expire or become irrelevant. |
| |
| * ``contrib.sessions`` data integrity check |
| |
| * consequences: the user will be logged out, and session data will be lost. |
| |
| * time period: defined by :setting:`SESSION_COOKIE_AGE`. |
| |
| * ``contrib.auth`` password reset hash |
| |
| * consequences: password reset links from before the upgrade will not work. |
| |
| * time period: defined by :setting:`PASSWORD_RESET_TIMEOUT_DAYS`. |
| |
| Form-related hashes — these are much shorter lifetime, and are relevant only for |
| the short window where a user might fill in a form generated by the pre-upgrade |
| Django instance, and try to submit it to the upgraded Django instance: |
| |
| * ``contrib.comments`` form security hash |
| |
| * consequences: the user will see a validation error "Security hash failed". |
| |
| * time period: the amount of time you expect users to take filling out comment |
| forms. |
| |
| * ``FormWizard`` security hash |
| |
| * consequences: the user will see an error about the form having expired, |
| and will be sent back to the first page of the wizard, losing the data |
| they have entered so far. |
| |
| * time period: the amount of time you expect users to take filling out the |
| affected forms. |
| |
| * CSRF check |
| |
| * Note: This is actually a Django 1.1 fallback, not Django 1.2, |
| and applies only if you are upgrading from 1.1. |
| |
| * consequences: the user will see a 403 error with any CSRF protected POST |
| form. |
| |
| * time period: the amount of time you expect user to take filling out |
| such forms. |
| |
| django.contrib.flatpages |
| ~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Starting in the 1.4 release the |
| :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` only |
| adds a trailing slash and redirects if the resulting URL refers to an existing |
| flatpage. For example, requesting ``/notaflatpageoravalidurl`` in a previous |
| version would redirect to ``/notaflatpageoravalidurl/``, which would |
| subsequently raise a 404. Requesting ``/notaflatpageoravalidurl`` now will |
| immediately raise a 404. Additionally redirects returned by flatpages are now |
| permanent (301 status code) to match the behavior of the |
| :class:`~django.middleware.common.CommonMiddleware`. |
| |
| Serialization of :class:`~datetime.datetime` and :class:`~datetime.time` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| As a consequence of time zone support, and according to the ECMA-262 |
| specification, some changes were made to the JSON serializer: |
| |
| - It includes the time zone for aware datetime objects. It raises an exception |
| for aware time objects. |
| - It includes milliseconds for datetime and time objects. There is still |
| some precision loss, because Python stores microseconds (6 digits) and JSON |
| only supports milliseconds (3 digits). However, it's better than discarding |
| microseconds entirely. |
| |
| The XML serializer was also changed to use the ISO8601 format for datetimes. |
| The letter ``T`` is used to separate the date part from the time part, instead |
| of a space. Time zone information is included in the ``[+-]HH:MM`` format. |
| |
| The serializers will dump datetimes in fixtures with these new formats. They |
| can still load fixtures that use the old format. |
| |
| ``supports_timezone`` changed to ``False`` for SQLite |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The database feature ``supports_timezone`` used to be ``True`` for SQLite. |
| Indeed, if you saved an aware datetime object, SQLite stored a string that |
| included an UTC offset. However, this offset was ignored when loading the value |
| back from the database, which could corrupt the data. |
| |
| In the context of time zone support, this flag was changed to ``False``, and |
| datetimes are now stored without time zone information in SQLite. When |
| :setting:`USE_TZ` is ``False``, if you attempt to save an aware datetime |
| object, Django raises an exception. |
| |
| Database connection's thread-locality |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| ``DatabaseWrapper`` objects (i.e. the connection objects referenced by |
| ``django.db.connection`` and ``django.db.connections["some_alias"]``) used to |
| be thread-local. They are now global objects in order to be potentially shared |
| between multiple threads. While the individual connection objects are now |
| global, the ``django.db.connections`` dictionary referencing those objects is |
| still thread-local. Therefore if you just use the ORM or |
| ``DatabaseWrapper.cursor()`` then the behavior is still the same as before. |
| Note, however, that ``django.db.connection`` does not directly reference the |
| default ``DatabaseWrapper`` object anymore and is now a proxy to access that |
| object's attributes. If you need to access the actual ``DatabaseWrapper`` |
| object, use ``django.db.connections[DEFAULT_DB_ALIAS]`` instead. |
| |
| As part of this change, all underlying SQLite connections are now enabled for |
| potential thread-sharing (by passing the ``check_same_thread=False`` attribute |
| to pysqlite). ``DatabaseWrapper`` however preserves the previous behavior by |
| disabling thread-sharing by default, so this does not affect any existing |
| code that purely relies on the ORM or on ``DatabaseWrapper.cursor()``. |
| |
| Finally, while it is now possible to pass connections between threads, Django |
| does not make any effort to synchronize access to the underlying backend. |
| Concurrency behavior is defined by the underlying backend implementation. |
| Check their documentation for details. |
| |
| `COMMENTS_BANNED_USERS_GROUP` setting |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django's :doc:`comments app </ref/contrib/comments/index>` has historically |
| supported excluding the comments of a special user group, but we've never |
| documented the feature properly and didn't enforce the exclusion in other parts |
| of the app such as the template tags. To fix this problem, we removed the code |
| from the feed class. |
| |
| If you rely on the feature and want to restore the old behavior, simply use |
| a custom comment model manager to exclude the user group, like this:: |
| |
| from django.conf import settings |
| from django.contrib.comments.managers import CommentManager |
| |
| class BanningCommentManager(CommentManager): |
| def get_query_set(self): |
| qs = super(BanningCommentManager, self).get_query_set() |
| if getattr(settings, 'COMMENTS_BANNED_USERS_GROUP', None): |
| where = ['user_id NOT IN (SELECT user_id FROM auth_user_groups WHERE group_id = %s)'] |
| params = [settings.COMMENTS_BANNED_USERS_GROUP] |
| qs = qs.extra(where=where, params=params) |
| return qs |
| |
| Save this model manager in your custom comment app (e.g. in |
| ``my_comments_app/managers.py``) and add it your |
| :ref:`custom comment app model <custom-comment-app-api>`:: |
| |
| from django.db import models |
| from django.contrib.comments.models import Comment |
| |
| from my_comments_app.managers import BanningCommentManager |
| |
| class CommentWithTitle(Comment): |
| title = models.CharField(max_length=300) |
| |
| objects = BanningCommentManager() |
| |
| For more details, see the documentation about |
| :doc:`customizing the comments framework </ref/contrib/comments/custom>`. |
| |
| `IGNORABLE_404_STARTS` and `IGNORABLE_404_ENDS` settings |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Until Django 1.3, it was possible to exclude some URLs from Django's |
| :doc:`404 error reporting</howto/error-reporting>` by adding prefixes to |
| :setting:`IGNORABLE_404_STARTS` and suffixes to :setting:`IGNORABLE_404_ENDS`. |
| |
| In Django 1.4, these two settings are superseded by |
| :setting:`IGNORABLE_404_URLS`, which is a list of compiled regular expressions. |
| Django won't send an email for 404 errors on URLs that match any of them. |
| |
| Furthermore, the previous settings had some rather arbitrary default values:: |
| |
| IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf') |
| IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', |
| 'favicon.ico', '.php') |
| |
| It's not Django's role to decide if your website has a legacy ``/cgi-bin/`` |
| section or a ``favicon.ico``. As a consequence, the default values of |
| :setting:`IGNORABLE_404_URLS`, :setting:`IGNORABLE_404_STARTS` and |
| :setting:`IGNORABLE_404_ENDS` are all now empty. |
| |
| If you have customized :setting:`IGNORABLE_404_STARTS` or |
| :setting:`IGNORABLE_404_ENDS`, or if you want to keep the old default value, |
| you should add the following lines in your settings file:: |
| |
| import re |
| IGNORABLE_404_URLS = ( |
| # for each <prefix> in IGNORABLE_404_STARTS |
| re.compile(r'^<prefix>'), |
| # for each <suffix> in IGNORABLE_404_ENDS |
| re.compile(r'<suffix>$'), |
| ) |
| |
| Don't forget to escape characters that have a special meaning in a regular |
| expression. |
| |
| CSRF protection extended to PUT and DELETE |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Previously, Django's :doc:`CSRF protection </ref/contrib/csrf/>` provided |
| protection against only POST requests. Since use of PUT and DELETE methods in |
| AJAX applications is becoming more common, we now protect all methods not |
| defined as safe by :rfc:`2616` i.e. we exempt GET, HEAD, OPTIONS and TRACE, and |
| enforce protection on everything else. |
| |
| If you are using PUT or DELETE methods in AJAX applications, please see the |
| :ref:`instructions about using AJAX and CSRF <csrf-ajax>`. |
| |
| ``django.core.template_loaders`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This was an alias to ``django.template.loader`` since 2005, it has been removed |
| without emitting a warning due to the length of the deprecation. If your code |
| still referenced this please use ``django.template.loader`` instead. |
| |
| ``django.db.models.fields.URLField.verify_exists`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This functionality has been removed due to intractable performance and |
| security issues. Any existing usage of ``verify_exists`` should be |
| removed. |
| |
| ``django.core.files.storage.Storage.open`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The ``open`` method of the base Storage class took an obscure parameter |
| ``mixin`` which allowed you to dynamically change the base classes of the |
| returned file object. This has been removed. In the rare case you relied on the |
| ``mixin`` parameter, you can easily achieve the same by overriding the ``open`` |
| method, e.g.:: |
| |
| from django.core.files import File |
| from django.core.files.storage import FileSystemStorage |
| |
| class Spam(File): |
| """ |
| Spam, spam, spam, spam and spam. |
| """ |
| def ham(self): |
| return 'eggs' |
| |
| class SpamStorage(FileSystemStorage): |
| """ |
| A custom file storage backend. |
| """ |
| def open(self, name, mode='rb'): |
| return Spam(open(self.path(name), mode)) |
| |
| YAML deserializer now uses ``yaml.safe_load`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| ``yaml.load`` is able to construct any Python object, which may trigger |
| arbitrary code execution if you process a YAML document that comes from an |
| untrusted source. This feature isn't necessary for Django's YAML deserializer, |
| whose primary use is to load fixtures consisting of simple objects. Even though |
| fixtures are trusted data, for additional security, the YAML deserializer now |
| uses ``yaml.safe_load``. |
| |
| Features deprecated in 1.4 |
| ========================== |
| |
| Old styles of calling ``cache_page`` decorator |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Some legacy ways of calling :func:`~django.views.decorators.cache.cache_page` |
| have been deprecated, please see the docs for the correct way to use this |
| decorator. |
| |
| Support for PostgreSQL versions older than 8.2 |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Django 1.3 dropped support for PostgreSQL versions older than 8.0 and the |
| relevant documents suggested to use a recent version because of performance |
| reasons but more importantly because end of the upstream support periods for |
| releases 8.0 and 8.1 was near (November 2010). |
| |
| Django 1.4 takes that policy further and sets 8.2 as the minimum PostgreSQL |
| version it officially supports. |
| |
| Request exceptions are now always logged |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| When :doc:`logging support </topics/logging/>` was added to Django in 1.3, the |
| admin error email support was moved into the |
| :class:`django.utils.log.AdminEmailHandler`, attached to the |
| ``'django.request'`` logger. In order to maintain the established behavior of |
| error emails, the ``'django.request'`` logger was called only when |
| :setting:`DEBUG` was ``False``. |
| |
| To increase the flexibility of error logging for requests, the |
| ``'django.request'`` logger is now called regardless of the value of |
| :setting:`DEBUG`, and the default settings file for new projects now includes a |
| separate filter attached to :class:`django.utils.log.AdminEmailHandler` to |
| prevent admin error emails in ``DEBUG`` mode:: |
| |
| 'filters': { |
| 'require_debug_false': { |
| '()': 'django.utils.log.RequireDebugFalse' |
| } |
| }, |
| 'handlers': { |
| 'mail_admins': { |
| 'level': 'ERROR', |
| 'filters': ['require_debug_false'], |
| 'class': 'django.utils.log.AdminEmailHandler' |
| } |
| }, |
| |
| If your project was created prior to this change, your :setting:`LOGGING` |
| setting will not include this new filter. In order to maintain |
| backwards-compatibility, Django will detect that your ``'mail_admins'`` handler |
| configuration includes no ``'filters'`` section, and will automatically add |
| this filter for you and issue a pending-deprecation warning. This will become a |
| deprecation warning in Django 1.5, and in Django 1.6 the |
| backwards-compatibility shim will be removed entirely. |
| |
| The existence of any ``'filters'`` key under the ``'mail_admins'`` handler will |
| disable this backward-compatibility shim and deprecation warning. |
| |
| ``django.conf.urls.defaults`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Until Django 1.3 the functions :func:`~django.conf.urls.include`, |
| :func:`~django.conf.urls.patterns` and :func:`~django.conf.urls.url` plus |
| :data:`~django.conf.urls.handler404`, :data:`~django.conf.urls.handler500` |
| were located in a ``django.conf.urls.defaults`` module. |
| |
| Starting with Django 1.4 they are now available in :mod:`django.conf.urls`. |
| |
| ``django.contrib.databrowse`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Databrowse has not seen active development for some time, and this does not show |
| any sign of changing. There had been a suggestion for a `GSOC project`_ to |
| integrate the functionality of databrowse into the admin, but no progress was |
| made. While Databrowse has been deprecated, an enhancement of |
| ``django.contrib.admin`` providing a similar feature set is still possible. |
| |
| .. _GSOC project: https://code.djangoproject.com/wiki/SummerOfCode2011#Integratedatabrowseintotheadmin |
| |
| The code that powers Databrowse is licensed under the same terms as Django |
| itself, and so is available to be adopted by an individual or group as |
| a third-party project. |
| |
| ``django.core.management.setup_environ`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This function temporarily modified ``sys.path`` in order to make the parent |
| "project" directory importable under the old flat :djadmin:`startproject` |
| layout. This function is now deprecated, as its path workarounds are no longer |
| needed with the new ``manage.py`` and default project layout. |
| |
| This function was never documented or part of the public API, but was widely |
| recommended for use in setting up a "Django environment" for a user script. |
| These uses should be replaced by setting the ``DJANGO_SETTINGS_MODULE`` |
| environment variable or using :func:`django.conf.settings.configure`. |
| |
| ``django.core.management.execute_manager`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This function was previously used by ``manage.py`` to execute a management |
| command. It is identical to |
| ``django.core.management.execute_from_command_line``, except that it first |
| calls ``setup_environ``, which is now deprecated. As such, ``execute_manager`` |
| is also deprecated; ``execute_from_command_line`` can be used instead. Neither |
| of these functions is documented as part of the public API, but a deprecation |
| path is needed due to use in existing ``manage.py`` files. |
| |
| ``is_safe`` and ``needs_autoescape`` attributes of template filters |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Two flags, ``is_safe`` and ``needs_autoescape``, define how each template filter |
| interacts with Django's auto-escaping behavior. They used to be attributes of |
| the filter function:: |
| |
| @register.filter |
| def noop(value): |
| return value |
| noop.is_safe = True |
| |
| However, this technique caused some problems in combination with decorators, |
| especially :func:`@stringfilter <django.template.defaultfilters.stringfilter>`. |
| Now, the flags are keyword arguments of :meth:`@register.filter |
| <django.template.Library.filter>`:: |
| |
| @register.filter(is_safe=True) |
| def noop(value): |
| return value |
| |
| See :ref:`filters and auto-escaping <filters-auto-escaping>` for more information. |
| |
| Session cookies now have the ``httponly`` flag by default |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Session cookies now include the ``httponly`` attribute by default to |
| help reduce the impact of potential XSS attacks. For strict backwards |
| compatibility, use ``SESSION_COOKIE_HTTPONLY = False`` in your settings file. |
| |
| Wildcard expansion of application names in `INSTALLED_APPS` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Until Django 1.3, :setting:`INSTALLED_APPS` accepted wildcards in application |
| names, like ``django.contrib.*``. The expansion was performed by a |
| filesystem-based implementation of ``from <package> import *``. Unfortunately, |
| `this can't be done reliably`_. |
| |
| This behavior was never documented. Since it is un-pythonic and not obviously |
| useful, it was removed in Django 1.4. If you relied on it, you must edit your |
| settings file to list all your applications explicitly. |
| |
| .. _this can't be done reliably: http://docs.python.org/tutorial/modules.html#importing-from-a-package |
| |
| ``HttpRequest.raw_post_data`` renamed to ``HttpRequest.body`` |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This attribute was confusingly named ``HttpRequest.raw_post_data``, but it |
| actually provided the body of the HTTP request. It's been renamed to |
| ``HttpRequest.body``, and ``HttpRequest.raw_post_data`` has been deprecated. |
| |
| The Django 1.4 roadmap |
| ====================== |
| |
| Before the final Django 1.4 release, several other preview/development releases |
| will be made available. The current schedule consists of at least the following: |
| |
| * Week of **January 30, 2012**: First Django 1.4 beta release; final |
| feature freeze for Django 1.4. |
| |
| * Week of **February 27, 2012**: First Django 1.4 release |
| candidate; string freeze for translations. |
| |
| * Week of **March 5, 2012**: Django 1.4 final release. |
| |
| If necessary, additional alpha, beta or release-candidate packages |
| will be issued prior to the final 1.4 release. Django 1.4 will be |
| released approximately one week after the final release candidate. |
| |
| What you can do to help |
| ======================= |
| |
| In order to provide a high-quality 1.4 release, we need your help. Although this |
| alpha release is, again, *not* intended for production use, you can help the |
| Django team by trying out the alpha codebase in a safe test environment and |
| reporting any bugs or issues you encounter. The Django ticket tracker is the |
| central place to search for open issues: |
| |
| * https://code.djangoproject.com/timeline |
| |
| Please open new tickets if no existing ticket corresponds to a problem you're |
| running into. |
| |
| Additionally, discussion of Django development, including progress toward the |
| 1.3 release, takes place daily on the django-developers mailing list: |
| |
| * http://groups.google.com/group/django-developers |
| |
| ... and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If you're |
| interested in helping out with Django's development, feel free to join the |
| discussions there. |
| |
| Django's online documentation also includes pointers on how to contribute to |
| Django: |
| |
| * :doc:`How to contribute to Django </internals/contributing/index>` |
| |
| Contributions on any level -- developing code, writing documentation or simply |
| triaging tickets and helping to test proposed bugfixes -- are always welcome and |
| appreciated. |
| |
| Several development sprints will also be taking place before the 1.4 |
| release; these will typically be announced in advance on the |
| django-developers mailing list, and anyone who wants to help is |
| welcome to join in. |