Open-Source Wikis

/

Django

/

How to contribute

/

Development workflow

django/django

Development workflow

The end-to-end cycle from picking up a Trac ticket to landing a merged PR.

Pick a ticket

Browse Trac for tickets in Accepted state with no current assignee. Good first tickets are tagged with Easy pickings. The ticket page shows the ticket type (Bug / Feature Request / Cleanup), a description, the affected version, and any prior discussion.

If you want to start from scratch — fix a behaviour you think is wrong, propose a new API — file the ticket first. Don't spend a weekend on code without consensus that the change should land.

Set up your branch

git checkout main
git pull
git checkout -b ticket_NNNNN

The branch name is informal. The PR title and commit message are what matter for downstream tooling.

Write a failing test first

Find the right test app under tests/:

ls tests/
# admin_views/  forms_tests/  migrations/  queries/  ...

Each subsystem has a dedicated app. The tests live alongside fixtures and model definitions. Add a new test method that reproduces the bug, run it, and confirm it fails:

cd tests
python runtests.py queries.test_my_new_test

Implement the fix

Edit the source under django/ and re-run the test until it passes. Then run the entire test app:

python runtests.py queries

If your change touches the ORM, run against multiple backends:

python runtests.py --settings test_postgres queries
python runtests.py --settings test_mysql queries

Backend-specific test settings live at tests/test_*.py. You'll need a running database server and the matching driver in your venv.

Update docs and release notes

Public API changes need:

  • A doc update in the relevant docs/ref/ or docs/topics/ file.
  • An entry in docs/releases/<next-version>.txt under "Bugfixes" or the relevant feature section.
  • An entry in docs/releases/<lts-versions>.txt if the bug is severe enough to backport.

Run the linters

Before pushing:

tox -e black flake8 isort lint-docs

Or if you have pre-commit installed:

pre-commit run --all-files

Commit message format

The commit message has a strict format because Trac and the release notes generator both parse it:

Fixed #NNNNN -- One-line summary in past tense.

Optional longer explanation wrapped at 79 columns.

Thanks <Reviewer Name> for the review.

For features that don't fix a specific bug:

Refs #NNNNN -- Added <feature>.

For changes with no Trac ticket (only typo fixes and trivial doc tweaks):

Fixed typo in <file>.

Open the PR

Push to your fork and open a PR against django/django:main. The PR description should:

  • Link to the Trac ticket.
  • Summarise the change in one paragraph.
  • Note any backport candidates (Backport candidate to 5.2 and 4.2).
  • Mention any breaking changes or deprecations.

Review

A core team member or DSF fellow will review. Common feedback patterns:

  • "Add a test for X edge case."
  • "This needs a deprecation cycle — see docs/internals/deprecation.txt."
  • "Update docs/releases/<version>.txt."
  • "The commit message should be Fixed #N -- not Fixes #N."

After review, you fix things and force-push to the same branch. A reviewer may rebase/squash before merging.

Backports

If the fix is a security issue, data-loss bug, or regression, the merger will cherry-pick to the supported LTS branches (stable/5.2.x, stable/4.2.x). You generally don't need to open separate PRs.

Release notes and Trac

Once merged, the merger updates Trac to Resolved/Fixed and references the commit hash. The release notes file is the source for docs.djangoproject.com/releases/.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Development workflow – Django wiki | Factory