Skip to content

Rules

ForwardRelationOverloadCodemod

A codemod that will add overloads to the __init__ methods of related fields.

Rule identifier: DJAS001.

Related settings:

This will provide auto-completion when using ForeignKey, OneToOneField and ManyToManyField with string references to a model, and accurate type checking when accessing the field attribute from a model instance.

class MyModel(models.Model):
    field = models.ForeignKey(
        "myapp.Other",
        on_delete=models.CASCADE,
    )
    nullable = models.OneToOneField(
        "myapp.Other",
        on_delete=models.CASCADE,
        null=True,
    )
reveal_type(MyModel().field)  # Revealed type is "Other"
reveal_type(MyModel().nullable)  # Revealed type is "Other | None"
Implementation

The following is a snippet of the produced overloads:

class ForeignKey(ForeignObject[_ST, _GT]):
    # For each model, will add two overloads:
    # - 1st: `null: Literal[True]`, which will parametrize `ForeignKey` types as `Optional`.
    # - 2nd: `null: Literal[False] = ...` (the default).
    # `to` is annotated as a `Literal`, with two values: {app_label}.{model_name} and {model_name}.
    @overload
    def __init__(
        self: ForeignKey[MyModel | Combinable | None, MyModel | None],
        to: Literal["MyModel", "myapp.MyModel"],
        ...
    ) -> None: ...

STUB_FILES = {'db/models/fields/related.pyi'}

CreateOverloadCodemod

A codemod that will add overloads to the create and acreate methods.

Rule identifier: DJAS002.

Related settings:

MyModel.objects.create(...)  # Signature is provided.
Implementation

This codemod makes use of the PEP 692. If your type checker/LSP supports it, documentation is provided for each field if help_text was set.

STUB_FILES = {'db/models/manager.pyi', 'db/models/query.pyi'}

ModelInitOverloadCodemod

A codemod that will add overloads to the Model.__init__ method.

Rule identifier: DJAS003.

Related settings:

MyModel(...)  # Signature is provided.
Implementation

This codemod makes use of the PEP 692. If your type checker/LSP supports it, documentation is provided for each field if help_text was set.

STUB_FILES = {'db/models/base.pyi'}

GetModelOverloadCodemod

A codemod that will add overloads to the apps.get_model method.

Rule identifier: DJAS010.

reveal_type(apps.get_model("app_name.ModelName"))  # Revealed type is "type[ModelName]"
reveal_type(apps.get_model("app_name", "ModelName"))  # Revealed type is "type[ModelName]"

STUB_FILES = {'apps/registry.pyi'}

AuthFunctionsCodemod

A codemod that will add a custom return type to the to auth related functions.

The following functions are affected:

Rule identifier: DJAS011.

from django.contrib.auth import authenticate, get_user_model, get_user

reveal_type(authenticate(rq, **creds))  # Revealed type is "YourCustomUser | None"
reveal_type(get_user_model())  # Revealed type is "type[YourCustomUser]"
reveal_type(get_user(rq))  # Revealed type is "YourCustomUser | AnonymousUser"

STUB_FILES = {'contrib/auth/__init__.pyi'}

ReverseOverloadCodemod

A codemod that will add overloads to the reverse function.

Rule identifier: DJAS015.

Related settings:

reverse("my-view-name", kwargs={...})  # `kwargs` is typed with a `TypedDict`, providing auto-completion.

STUB_FILES = {'urls/base.pyi'}

SettingCodemod

A codemod that will add typing to the Django settings object.

Depending on the Django version being used when running the stubs generation, the available settings might differ. The @deprecated decorator will be used if necessary, thus making your type checker aware of the deprecation notice.

Rule identifier: DJAS016.

from django.conf import settings

reveal_type(settings.ADMINS)  # Revealed type is "list[tuple[str, str]]"
reveal_type(settings.CUSTOM_SETTING)  # Revealed type is "str"
reveal_type(settings.USE_DEPRECATED_PYTZ)  # Will be marked as deprecated by the type checker.

Experimental

Type hints might not reflect the actual type being used at runtime. For Django settings, all the possible types are taken into account (e.g. the EMAIL_TIMEOUT setting might be set to 10, but as the default value is None, the reflected type hint will be int | None).

For custom settings, only simple types are inferred. See this issue for more details.

STUB_FILES = {'conf/__init__.pyi'}

TemplateLoadingCodemod

A codemod that will add overloads for template loading functions:

Rule identifier: DJAS017.

from django.template.loader import get_template

get_template("a_template.html")  # 'a_template.html' can be from any engine
get_template("a_django_template.html", using="django")
get_template("not_a_jinja2_template.html", using="my_jinja2_engine")  # Type error

Limited support

Engines other that Django and custom loaders are not supported yet.

STUB_FILES = {'template/loader.pyi'}