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:
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:
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
¶
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.