123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125 |
- ==============================
- 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
- ``IGNORABLE_404_STARTS`` and suffixes to ``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`, ``IGNORABLE_404_STARTS``, and
- ``IGNORABLE_404_ENDS`` are all now empty.
- If you have customized ``IGNORABLE_404_STARTS`` or ``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.
|