Contribution Guide
We welcome contributions to Django-Chassis. This guide covers the local workflow for development, testing, and documentation.
If you are not sure whether a change fits the project, open an issue or a draft pull request first.
Please keep changes focused and include tests when behavior changes.
Setting up environment
The project uses uv for Python dependency management. To install it, follow
the official guide in the
uv documentation.
After cloning the repository, install dependencies:
uv sync --group dev
Linting
uv run ruff check .
uv run pyrefly check
uv run pytest tests/test_source_conventions.py -q
Ruff checks both the package and the test suite. Keep rule exceptions scoped
to the narrowest matching file or path and document why the framework contract
requires them. The configured Cyrillic confusables support Russian UI strings
and docstrings without disabling the RUF001–RUF003 checks.
B009 and B010 are disabled because Django integrations legitimately read
and attach dynamic attributes on framework objects with getattr() and
setattr(); forcing direct access would require artificial protocols solely
for the type checker.
Pyrefly checks django_chassis with the strict preset and the minimum supported
Python version. The stylistic missing-override-decorator and
implicit-any-lambda rules are disabled. implicit-any-attribute is disabled
to keep Django model Meta assignments unannotated; incompatible method
signatures remain errors through bad-override.
Testing
uv run pytest
The GitHub Actions test pipeline runs linting and strict type checks on Python 3.13, then runs the complete test suite on Python 3.13 and 3.14. Matrix jobs do not stop after the first failure, so every supported Python version reports its result.
Working with documentation
Documentation is built with Docusaurus. The site
is bilingual (English source, Russian mirrors) and is not versioned.
Public API is marked with <Since v="x.y.z" /> badges instead.
cd docs
npm install
npm run docs:dev
English is the default locale at /. Russian is the i18n overlay at /ru/.
docs:dev serves English on port 3000, Russian on 3001 (under /ru/), and
proxies /ru from the English server so the locale dropdown works. Use
docs:dev, not docs:dev:ru alone, if you need to switch languages.
npm run docs:build
npm run docs:serve
Version badges
Any new public option, component, page, setting, or extra must be marked in both languages:
<Since v="1.1.0" />
Behaviour or signature changes use <Changed v="..." /> and a
CHANGELOG.md entry. The badge version is the package version that first
shipped the feature, not a documentation version.
Project conventions
- Full typing — annotate every function parameter, return value, and
variable except attributes inside Django model
Metaclasses. The project targetspyreflystrict mode. Runtime Django classes that do not support parameterization, such asFieldandModelAdmin, remain unparameterized in annotations. - No relative imports — always use absolute imports
(
from django_chassis.mixins import ChassisAdminMixin). - Keyword arguments — pass arguments by keyword where possible.
- Function signatures — if a signature does not fit on one line, put every parameter on its own line.
- Trailing commas — do not leave an optional comma after the final
parameter, argument, or collection item. Ruff formatter is disabled because
it requires trailing commas in multiline collections.
COM819handles its supported cases, and the source-conventions checker covers multiline syntax. - Formatting — do not run
ruff format; useuv run ruff check .for automated style checks. - Migrations — never edit or mechanically rewrite files in Django
migrationsdirectories. They are globally excluded from pre-commit, Ruff, Pyrefly, and source-conventions checks. - Imports —
I001is disabled because isort requires trailing commas in multiline import blocks. Absolute-import enforcement remains enabled. - Lambda expressions — preserve concise lambdas; do not replace them with named functions or direct references solely for linting or typing.
- Noqa directives — preserve existing
# noqacomments; do not remove or rewrite maintainer-added suppressions unless explicitly requested. - Model managers — declare Django model
ManagerandQuerySetclasses indjango_chassis.models.managers, not in model modules. - Django model metadata — use plain assignments inside model
Metaclasses; do not add type annotations, including todefault_permissions = (). The source-conventions checker enforces this; Pyrefly'simplicit-any-attributerule is disabled so it cannot require an annotation for an empty tuple. - Class names — do not create classes whose names start with
_without explicit maintainer permission; use a descriptive public name instead. uv run— run Python commands asuv run pytest, not barepython.optionsstaysoptions— do not rename the ModelAdmin attribute.- Mixin order —
ChassisAdminMixin/ChassisAdminSiteMixinbefore the Django class. INSTALLED_APPSorder —'django_chassis'before'django.contrib.admin'.- English and Russian docs stay in sync.
- Public API changes need a
CHANGELOG.mdentry.