0
# Runtime Monkey-Patching
1
2
The core functionality of django-stubs-ext that dynamically adds generic type support to Django classes at runtime. This system enables proper type parameterization for Django classes that don't natively support the `__class_getitem__` method.
3
4
## Capabilities
5
6
### Main Patching Function
7
8
Applies runtime monkey-patches to Django classes for generic type support. This function should be called once in your Django application settings.
9
10
```python { .api }
11
def monkeypatch(
12
extra_classes: Optional[Iterable[type]] = None,
13
include_builtins: bool = True
14
) -> None:
15
"""
16
Monkey patch Django as necessary to work properly with mypy.
17
18
Parameters:
19
- extra_classes: Optional iterable of additional classes to patch
20
- include_builtins: Whether to add reveal_type and reveal_locals helpers
21
22
Returns:
23
None
24
"""
25
```
26
27
### Usage Examples
28
29
Basic usage in Django settings:
30
31
```python
32
# In your Django settings file
33
import django_stubs_ext
34
35
django_stubs_ext.monkeypatch()
36
```
37
38
With additional classes:
39
40
```python
41
import django_stubs_ext
42
from my_app.models import CustomModel
43
44
# Patch additional classes
45
django_stubs_ext.monkeypatch(extra_classes=[CustomModel])
46
```
47
48
Without mypy helpers:
49
50
```python
51
import django_stubs_ext
52
53
# Skip adding reveal_type and reveal_locals to builtins
54
django_stubs_ext.monkeypatch(include_builtins=False)
55
```
56
57
### Supported Django Classes
58
59
The following Django classes are automatically patched when appropriate for the detected Django version:
60
61
#### Always Patched Classes
62
- `django.contrib.admin.ModelAdmin`
63
- `django.views.generic.detail.SingleObjectMixin`
64
- `django.views.generic.edit.FormMixin`
65
- `django.views.generic.edit.DeletionMixin`
66
- `django.views.generic.list.MultipleObjectMixin`
67
- `django.contrib.admin.options.BaseModelAdmin`
68
- `django.db.models.fields.Field`
69
- `django.core.paginator.Paginator`
70
- `django.forms.formsets.BaseFormSet`
71
- `django.forms.models.BaseModelForm`
72
- `django.forms.models.BaseModelFormSet`
73
- `django.contrib.syndication.views.Feed`
74
- `django.contrib.sitemaps.Sitemap`
75
- `django.contrib.messages.views.SuccessMessageMixin`
76
- `django.core.files.utils.FileProxyMixin`
77
- `django.db.models.lookups.Lookup`
78
- `django.utils.connection.BaseConnectionHandler`
79
- `django.db.models.expressions.ExpressionWrapper`
80
81
#### Version-Specific Classes
82
- `django.db.models.query.QuerySet` (Django ≤ 3.1)
83
- `django.db.models.manager.BaseManager` (Django ≤ 3.1)
84
- `django.db.models.fields.related.ForeignKey` (Django ≤ 4.1)
85
86
### Version Compatibility
87
88
The monkey-patching system automatically detects your Django version and only applies patches needed for your specific version:
89
90
```python
91
from django import VERSION
92
93
# Only patch classes that need it for the current Django version
94
suited_for_this_version = filter(
95
lambda spec: spec.version is None or VERSION[:2] <= spec.version,
96
_need_generic,
97
)
98
```
99
100
### Builtins Integration
101
102
When `include_builtins=True` (default), the following helpers are added to Python's builtins:
103
104
```python { .api }
105
def reveal_type(obj: Any) -> None:
106
"""Mypy helper function for type inspection (no-op at runtime)."""
107
108
def reveal_locals() -> None:
109
"""Mypy helper function for local variable inspection (no-op at runtime)."""
110
```
111
112
## Types
113
114
```python { .api }
115
from typing import Any, Generic, Iterable, List, Optional, Tuple, Type, TypeVar
116
117
_T = TypeVar("_T")
118
_VersionSpec = Tuple[int, int]
119
120
class MPGeneric(Generic[_T]):
121
"""
122
Metadata container for generic classes needing monkeypatching.
123
124
The version param is optional, and None means version-independent patching.
125
"""
126
127
def __init__(self, cls: Type[_T], version: Optional[_VersionSpec] = None) -> None:
128
"""Set the data fields, basic constructor."""
129
130
def __repr__(self) -> str:
131
"""Better representation in tests and debug."""
132
```