django-types
django-types provides essential type stubs for the Django framework, enabling comprehensive static type checking of Django projects using tools like mypy. It works by augmenting existing Django imports with type information. The current version is 0.23.0, and it's actively maintained with releases tied to Django's lifecycle and bug fixes.
Warnings
- breaking django-types provides type stubs for specific Django versions. Using a version of `django-types` that is incompatible with your installed `Django` version can lead to incorrect type checking results or errors.
- gotcha For `django-types` to function correctly, you *must* enable the `mypy_django_plugin` in your `mypy` configuration (e.g., `mypy.ini`, `pyproject.toml`). Without it, `mypy` will not apply the Django-specific type logic.
- gotcha When running `mypy`, it needs to be able to locate your Django settings module. This often requires setting `PYTHONPATH` correctly or explicitly passing the settings module via a `mypy.ini` configuration or command-line argument.
Install
-
pip install django-types mypy django
Imports
- Model
from django.db.models import Model
- HttpRequest
from django.http import HttpRequest
Quickstart
import os
import sys
from pathlib import Path
# Simulate a minimal Django project structure for type checking
project_dir = Path('./myproject_for_typechecking')
project_dir.mkdir(exist_ok=True)
(project_dir / '__init__.py').touch(exist_ok=True)
# Simulate app creation
app_dir = project_dir / 'myapp'
app_dir.mkdir(exist_ok=True)
(app_dir / '__init__.py').touch(exist_ok=True)
# Create a dummy settings.py
settings_content = '''
INSTALLED_APPS = ['myapp']
SECRET_KEY = 'insecure-key-for-testing'
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}}
'''
(project_dir / 'settings.py').write_text(settings_content)
# Create a typed model in myapp/models.py
models_content = '''
from django.db import models
class MyTypedModel(models.Model):
name = models.CharField(max_length=255)
value = models.IntegerField(default=0)
class Meta:
app_label = 'myapp'
def get_model_instance() -> MyTypedModel:
# This function is just to demonstrate type hints
return MyTypedModel(name='Test', value=10)
'''
(app_dir / 'models.py').write_text(models_content)
# Create a mypy configuration file
mypy_config_content = '''
[mypy]
plugins = mypy_django_plugin.main
[mypy.plugins.django_settings]
module = myproject_for_typechecking.settings
'''
(Path('.') / 'mypy.ini').write_text(mypy_config_content)
print("Generated project structure and mypy.ini. Now run:")
print(" PYTHONPATH=. mypy myproject_for_typechecking")
# Clean up (optional, for actual runtime) - commented out for user to inspect files
# import shutil
# shutil.rmtree(project_dir)
# (Path('.') / 'mypy.ini').unlink()