======================
Contributing to Django
======================

If you think working *with* Django is fun, wait until you start working *on* it.
We're passionate about helping Django users make the jump to contributing members
of the community, so there are many ways you can help Django's development:

    * Blog about Django.  We syndicate all the Django blogs we know about on
      the `community page`_; contact jacob@jacobian.org if you've got a blog
      you'd like to see on that page.

    * Report bugs and request features in our `ticket tracker`_.  Please read
      `Reporting bugs`_, below, for the details on how we like our bug reports
      served up.

    * Submit patches for new and/or fixed behavior.  Please read `Submitting
      patches`_, below, for details on how to submit a patch.

    * Join the `django-developers`_ mailing list and share your ideas for how
      to improve Django.  We're always open to suggestions, although we're
      likely to be skeptical of large-scale suggestions without some code to
      back it up.

That's all you need to know if you'd like to join the Django development
community. The rest of this document describes the details of how our community
works and how it handles bugs, mailing lists, and all the other minutiae of
Django development.

Reporting bugs
==============

Well-written bug reports are *incredibly* helpful. However, there's a certain
amount of overhead involved in working with any bug tracking system, so your
help in keeping our ticket tracker as useful as possible is appreciated.  In
particular:

    * **Do** read the FAQ_ to see if your issue might be a well-known question.

    * **Do** `search the tracker`_ to see if your issue has already been filed.

    * **Do** ask on `django-users`_ *first* if you're not sure if what you're
      seeing is a bug.

    * **Do** write complete, reproducible, specific bug reports. Include as
      much information as you possibly can, complete with code snippets, test
      cases, etc.  A minimal example that illustrates the bug in a nice small
      test case is the best possible bug report.

    * **Don't** use the ticket system to ask support questions.  Use the
      `django-users`_ list, or the `#django`_ IRC channel for that.

    * **Don't** use the ticket system to make large-scale feature requests.
      We like to discuss any big changes to Django's core on the `django-developers`_
      list before actually working on them.

    * **Don't** reopen issues that have been marked "wontfix". This mark means
      that the decision has been made that we can't or won't fix this particular
      issue.  If you're not sure why, please ask on `django-developers`_.

    * **Don't** use the ticket tracker for lengthy discussions, because they're
      likely to get lost. If a particular ticket is controversial, please move
      discussion to `django-developers`_.

Reporting security issues
=========================

Report security issues to security@djangoproject.com. This is a private list
only open to long-time, highly trusted Django developers, and its archives are
not publicly readable.

In the event of a confirmed vulnerability in Django itself, we will take the
following actions:

    * Acknowledge to the reporter that we've received the report and that a fix
      is forthcoming. We'll give a rough timeline and ask the reporter to keep
      the issue confidential until we announce it.

    * Halt all other development as long as is needed to develop a fix, including
      patches against the current and two previous releases.

    * Determine a go-public date for announcing the vulnerability and the fix.
      To try to mitigate a possible "arms race" between those applying the patch
      and those trying to exploit the hole, we will not announce security
      problems immediately.

    * Pre-notify everyone we know to be running the affected version(s) of
      Django. We will send these notifications through private e-mail which will
      include documentation of the vulnerability, links to the relevant patch(es),
      and a request to keep the vulnerability confidential until the official
      go-public date.

    * Publicly announce the vulnerability and the fix on the pre-determined
      go-public date. This will probably mean a new release of Django, but
      in some cases it may simply be patches against current releases.

Submitting patches
==================

We're always grateful for patches to Django's code. Indeed, bug reports with
associated patches will get fixed *far* more quickly than those without patches.

Patch style
-----------

    * Make sure your code matches our `coding style`_.

    * Submit patches in the format returned by the ``svn diff`` command.
      An exception is for code changes that are described more clearly in plain
      English than in code. Indentation is the most common example; it's hard to
      read patches when the only difference in code is that it's indented.

    * Attach patches to a ticket in the `ticket tracker`_, using the "attach file"
      button. Please *don't* put the patch in the ticket description or comment
      unless it's a single line patch.

    * Name the patch file with a ``.diff`` extension; this will let the ticket
      tracker apply correct syntax highlighting, which is quite helpful.

    * Put the prefix "[patch] " before the title of your ticket. This will make
      it obvious that the ticket includes a patch, and it will add the ticket
      to the `list of tickets with patches`_.

Submitting and maintaining translations
=======================================

Various parts of Django, such as the admin site and validator error messages,
are internationalized. This means they display different text depending on a
user's language setting.

These translations are contributed by Django users worldwide. If you find an
incorrect translation, or if you'd like to add a language that isn't yet
translated, here's what to do:

    * Join the `Django i18n mailing list`_ and introduce yourself.
    * Create and submit translations using the methods described in the
      `i18n documentation`_.

.. _Django i18n mailing list: http://groups.google.com/group/django-i18n/
.. _i18n documentation: http://www.djangoproject.com/documentation/i18n/

Coding style
============

Please follow these coding standards when writing code for inclusion in Django:

    * Unless otherwise specified, follow `PEP 8`_.

    * Use four spaces for indentation.

    * Use underscores, not camelCase, for variable, function and method names
      (i.e. ``poll.get_unique_voters()``, not ``poll.getUniqueVoters``).

    * Use ``InitialCaps`` for class names (or for factory functions that
      return classes).

    * Mark all strings for internationalization; see the `i18n documentation`_
      for details.

    * In Django template code, put one (and only one) space between the curly
      brackets and the tag contents.

      Do this::

          {{ foo }}

      Don't do this::

          {{foo}}

    * Please don't put your name in the code. While we appreciate all
      contributions to Django, our policy is not to publish individual
      developer names in code -- for instance, at the top of Python modules.

Committing code
===============

Please follow these guidelines when committing code to Django's Subversion
repository:

    * For any medium-to-big changes, where "medium-to-big" is according to your
      judgment, please bring things up on the `django-developers`_ mailing list
      before making the change.

      If you bring something up on `django-developers`_ and nobody responds,
      please don't take that to mean your idea is great and should be
      implemented immediately because nobody contested it. Django's lead
      developers don't have a lot of time to read mailing-list discussions
      immediately, so you may have to wait a couple of days before getting a
      response.

    * Write detailed commit messages in the past tense, not present tense.

          * Good: "Fixed Unicode bug in RSS API."
          * Bad: "Fixes Unicode bug in RSS API."
          * Bad: "Fixing Unicode bug in RSS API."

    * For commits to a branch, prefix the commit message with the branch name.
      For example: "magic-removal: Added support for mind reading."

    * Limit commits to the most granular change that makes sense. This means,
      use frequent small commits rather than infrequent large commits. For
      example, if implementing feature X requires a small change to library Y,
      first commit the change to library Y, then commit feature X in a separate
      commit. This goes a *long way* in helping all core Django developers
      follow your changes.

    * If your commit closes a ticket in the Django `ticket tracker`_, begin
      your commit message with the text "Fixed #abc", where "abc" is the number
      of the ticket your commit fixes. Example: "Fixed #123 -- Added support
      for foo". We've rigged Subversion and Trac so that any commit message
      in that format will automatically close the referenced ticket and post a
      comment to it with the full commit message.

      If your commit closes a ticket and is in a branch, use the branch name
      first, then the "Fixed #abc." For example:
      "magic-removal: Fixed #123 -- Added whizbang feature."

      For the curious: We're using a `Trac post-commit hook`_ for this.

      .. _Trac post-commit hook: http://trac.edgewall.org/browser/trunk/contrib/trac-post-commit-hook

    * If your commit references a ticket in the Django `ticket tracker`_ but
      does *not* close the ticket, include the phrase "Refs #abc", where "abc"
      is the number of the ticket your commit references. We've rigged
      Subversion and Trac so that any commit message in that format will
      automatically post a comment to the appropriate ticket.

Unit tests
==========

Django comes with a test suite of its own, in the ``tests`` directory of the
Django tarball. It's our policy to make sure all tests pass at all times.

The tests cover:

    * Models and the database API (``tests/testapp/models``).
    * The cache system (``tests/otherthests/cache.py``).
    * The ``django.utils.dateformat`` module (``tests/othertests/dateformat.py``).
    * Database typecasts (``tests/othertests/db_typecasts.py``).
    * The template system (``tests/othertests/templates.py`` and
      ``tests/othertests/defaultfilters.py``).
    * ``QueryDict`` objects (``tests/othertests/httpwrappers.py``).
    * Markup template tags (``tests/othertests/markup.py``).
    * The ``django.utils.timesince`` module (``tests/othertests/timesince.py``).

We appreciate any and all contributions to the test suite!

Running the unit tests
----------------------

To run the tests, ``cd`` to the ``tests/`` directory and type::

    ./runtests.py --settings=path.to.django.settings

Yes, the unit tests need a settings module, but only for database connection
info -- the ``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD``.

The unit tests will not touch your database; they create a new database, called
``django_test_db``, which is deleted when the tests are finished. This means
your user account needs permission to execute ``CREATE DATABASE``.

Requesting features
===================

We're always trying to make Django better, and your feature requests are a key
part of that. Here are some tips on how to most effectively make a request:

    * Request the feature on `django-developers`_, not in the ticket tracker;
      it'll get read more closely if it's on the mailing list.

    * Describe clearly and concisely what the missing feature is and how you'd
      like to see it implemented. Include example code (non-functional is OK)
      if possible.

    * Explain *why* you'd like the feature. In some cases this is obvious, but
      since Django is designed to help real developers get real work done,
      you'll need to explain it, if it isn't obvious why the feature would be
      useful.

As with most open-source projects, code talks. If you are willing to write the
code for the feature yourself or if (even better) you've already written it,
it's much more likely to be accepted.  If it's a large feature that might need
multiple developers we're always happy to give you an experimental branch in
our repository; see below.

Branch policy
=============

In general, most development is confined to the trunk, and the trunk
is kept stable. People should be able to run production sites against the
trunk at any time.

Thus, large architectural changes -- that is, changes too large to be
encapsulated in a single patch, or changes that need multiple eyes on them --
will have dedicated branches. See, for example, the `i18n branch`_. If you
have a change of this nature that you'd like to work on, ask on
`django-developers`_ for a branch to be created for you. We'll create a branch
for pretty much any kind of experimenting you'd like to do.

We will only branch entire copies of the Django tree, even if work is only
happening on part of that tree. This makes it painless to switch to a branch.

Developers working on a branch should periodically merge changes from the trunk
into the branch. Please merge at least once a week. Every time you merge from
the trunk, note the merge and revision numbers in the commit message.

Once the branch is stable and ready to be merged into the trunk, alert
`django-developers`_.

After a branch has been merged, it should be considered "dead"; write access to
it will be disabled, and old branches will be periodically "trimmed." To keep
our SVN wrangling to a minimum, we won't be merging from a given branch into the
trunk more than once.

Using branches
--------------

To test a given branch, you can simply check out the entire branch, like so::

    svn co http://code.djangoproject.com/svn/django/branches/<branch>/

Or, if you've got a working directory you'd like to switch to use a branch,
you can use::

    svn switch http://code.djangoproject.com/svn/django/branches/<branch>/

...in the root of your Django sandbox (the directory that contains ``django``,
``docs``, and ``tests``).

The advantage of using ``svn switch`` instead of ``svn co`` is that the
``switch`` command retains any changes you might have made to your local copy
of the code. It attempts to merge those changes into the "switched" code.

Official releases
=================

Django's release numbering works as follows:

    * Versions are numbered in the form ``A.B`` or ``A.B.C``.

    * ``A`` is the major version number, which is only incremented for major
      changes to Django, and these changes are not necessarily
      backwards-compatible. That is, code you wrote for Django 6.0 may break
      when we release Django 7.0.

    * ``B`` is the minor version number, which is incremented for large yet
      backwards compatible changes.  Code written for Django 6.4 will continue
      to work under Django 6.5.

      A minor release may deprecate certain features in previous releases. If a
      feature in version ``A.B`` is deprecated, it will continue to work in
      version ``A.B+1``. In version ``A.B+2``, use of the feature will raise a
      ``PendingDeprecationWarning`` but will continue to work.  Version
      ``A.B+3`` will remove the feature entirely. Major point releases will
      always remove deprecated features immediately.

    * ``C`` is the micro version number which, is incremented for bug and
      security fixes.  A new micro-release will always be 100%
      backwards-compatible with the previous micro-release.

    * In some cases, we'll make release candidate releases. These are of the
      form ``A.BrcN``, which means the ``Nth`` candidate release of version
      ``A.B``.

An exception to this version numbering scheme is the pre-1.0 Django code.
There's no guarantee of backwards-compatibility until the 1.0 release.

In Subversion, each Django release will be tagged under `tags/releases`_.  If
it's necessary to release a bug fix release or a security release that doesn't
come from the trunk, we'll copy that tag to ``branches/releases`` to make the
bug fix release.

Deciding on features
====================

Once a feature's been requested and discussed, eventually we'll have a decision
about whether to include the feature or drop it.

Whenever possible, we strive for a rough consensus. To that end, we'll often
have informal votes on `django-developers`_ about a feature. In these votes we
follow the voting style invented by Apache and used on Python itself, where
votes are given as +1, +0, -0, or -1.  Roughly translated, these votes mean:

    * +1: "I love the idea and I'm strongly committed to it."

    * +0: "Sounds OK to me."

    * -0: "I'm not thrilled, but I won't stand in the way."

    * -1: "I strongly disagree and would be very unhappy to see the idea turn
      into reality."

Although these votes on django-developers are informal, they'll be taken very
seriously. After a suitable voting period, if an obvious consensus arises
we'll follow the votes.

However, consensus is not always possible.  Tough decisions will be discussed by
all full committers and finally decided by the Benevolent Dictators for Life,
Adrian and Jacob.

Commit access
=============

Django has two types of committers:

Full committers
    These are people who have a long history of contributions to Django's
    codebase, a solid track record of being polite and helpful on the mailing
    lists, and a proven desire to dedicate serious time to Django's development.

    The bar is very high for full commit access. It will only be granted by
    unanimous approval of all existing full committers, and the decision will err
    on the side of rejection.

Partial committers
    These are people who are "domain experts." They have direct check-in access
    to the subsystems that fall under their jurisdiction, and they're given a
    formal vote in questions that involve their subsystems. This type of access
    is likely to be given to someone who contributes a large subframework to
    Django and wants to continue to maintain it.

    Like full committers, partial commit access is by unanimous approval of all
    full committers (and any other partial committers in the same area).
    However, the bar is set lower; proven expertise in the area in question is
    likely to be sufficient.

To request commit access, please contact an existing committer privately. Public
requests for commit access are potential flame-war starters, and will be ignored.

.. _community page: http://www.djangoproject.com/community/
.. _ticket tracker: http://code.djangoproject.com/newticket
.. _django-developers: http://groups.google.com/group/django-developers
.. _FAQ: http://www.djangoproject.com/documentation/faq/
.. _search the tracker: http://code.djangoproject.com/search
.. _django-users: http://groups.google.com/group/django-users
.. _`#django`: irc://irc.freenode.net/django
.. _list of tickets with patches: http://code.djangoproject.com/report/12
.. _PEP 8: http://www.python.org/peps/pep-0008.html
.. _i18n documentation: http://www.djangoproject.com/documentation/i18n/
.. _i18n branch: http://code.djangoproject.com/browser/django/branches/i18n
.. _`tags/releases`: http://code.djangoproject.com/browser/django/tags/releases
