Mypy stubs for Django
pep484 stubs for Django
This package contains type stubs and a custom mypy plugin to provide more precise static types and type inference for Django framework. Django uses some Python "magic" that makes having precise types for some code patterns problematic. This is why we need this project. The final goal is to be able to get precise types for most common patterns.
pip install django-stubs
To make mypy aware of the plugin, you need to add
[mypy] plugins = mypy_django_plugin.main [mypy.plugins.django-stubs] django_settings_module = "myproject.settings"
Two things happeining here:
- We need to explicitly list our plugin to be loaded by
- Our plugin also requires
djangosettings module (what you put into
DJANGO_SETTINGS_MODULEvariable) to be specified
This fully working typed boilerplate can serve you as an example.
We rely on different
|django-stubs||mypy version||django version||python version|
|1.8.0||0.812||2.2.x || 3.x||^3.6|
|1.7.0||0.790||2.2.x || 3.x||^3.6|
|1.6.0||0.780||2.2.x || 3.x||^3.6|
|1.5.0||0.770||2.2.x || 3.x||^3.6|
|1.4.0||0.760||2.2.x || 3.x||^3.6|
|1.3.0||0.750||2.2.x || 3.x||^3.6|
|0.12.x||old semantic analyzer (<0.711), dmypy support||2.1.x||^3.6|
Is this an official Django project?
No, it is not. We are independent from Django at the moment. There's a proposal to merge our project into the Django itself. You can show your support by liking the PR.
Is it safe to use this in production?
Yes, it is! This project does not affect your runtime at all.
It only affects
mypy type checking process.
But, it does not make any sense to use this project without
mypy crashes when I run it with this plugin installed
Current implementation uses Django runtime to extract models information, so it will crash, if your installed apps or
models.py is not correct. For this same reason, you cannot use
reveal_type inside global scope of any Python file that will be executed for
In other words, if your
manage.py runserver crashes, mypy will crash too.
You can also run
option to get extra information about the error.
I cannot use QuerySet or Manager with type annotations
You can get a
TypeError: 'type' object is not subscriptable
when you will try to use
Manager[MyModel] or some other Django-based Generic types.
This happens because these Django classes do not support
__class_getitem__ magic method in runtime.
- You can go with our
django_stubs_exthelper, that patches all the types we use as Generic in django.
pip install django-stubs-ext # as a production dependency
And then place in your top-level settings:
import django_stubs_ext django_stubs_ext.monkeypatch()
- You can use strings instead:
'Manager[MyModel]', this way it will work as a type for
mypyand as a regular
How can I create a HttpRequest that's guaranteed to have an authenticated user?
Django's built in
HttpRequest has the attribute
user that resolves to the type
User is the user model specified by the
If you want a
HttpRequest that you can type-annotate with where you know that the user is authenticated you can subclass the normal
HttpRequest class like so:
from django.http import HttpRequest from my_user_app.models import MyUser class AuthenticatedHttpRequest(HttpRequest): user: MyUser
And then use
AuthenticatedHttpRequest instead of the standard
HttpRequest for when you know that the user is authenticated. For example in views using the
My QuerySet methods are returning Any rather than my Model
QuerySet.as_manager() is not currently supported.
If you are using
MyQuerySet.as_manager(), then your
QuerySet methods will all not be linked to your model.
from django.db import models class MyModelQuerySet(models.QuerySet): pass class MyModel(models.Model): bar = models.IntegerField() objects = MyModelQuerySet.as_manager() def use_my_model(): foo = MyModel.objects.get(id=1) # This is `Any` but it should be `MyModel` return foo.xyz # No error, but there should be
There is a workaround: use
from django.db import models class MyModelQuerySet(models.QuerySet): pass MyModelManager = models.Manager.from_queryset(MyModelQuerySet) class MyModel(models.Model): bar = models.IntegerField() objects = MyModelManager() def use_my_model(): foo = MyModel.objects.get(id=1) return foo.xyz # Gives an error
awesome-python-typing- Awesome list of all typing-related things in Python.
djangorestframework-stubs- Stubs for Django REST Framework.
pytestplugin that we use for testing
mypystubs and plugins.
wemake-django-template- Create new typed Django projects in seconds.
To get help
This project is open source and community driven. As such we encourage contributions big and small. You can contribute by doing any of the following:
- Contribute code (e.g. improve stubs, add plugin capabilities, write tests etc) - to do so please follow the contribution guide.
- Assist in code reviews and discussions in issues.
- Identify bugs and issues and report these
You can always also reach out in gitter to discuss your contributions!
Release history Release notifications | RSS feed
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
|Filename, size||File type||Python version||Upload date||Hashes|
|Filename, size django_stubs-1.8.0-py3-none-any.whl (392.6 kB)||File type Wheel||Python version py3||Upload date||Hashes View|
|Filename, size django-stubs-1.8.0.tar.gz (205.1 kB)||File type Source||Python version None||Upload date||Hashes View|
Hashes for django_stubs-1.8.0-py3-none-any.whl