mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-15 00:07:09 +08:00
Adds docs for how Field access works
This commit is contained in:
@@ -43,6 +43,64 @@ _ST = TypeVar("_ST", contravariant=True)
|
|||||||
_GT = TypeVar("_GT", covariant=True)
|
_GT = TypeVar("_GT", covariant=True)
|
||||||
|
|
||||||
class Field(RegisterLookupMixin, Generic[_ST, _GT]):
|
class Field(RegisterLookupMixin, Generic[_ST, _GT]):
|
||||||
|
"""
|
||||||
|
Typing model fields.
|
||||||
|
|
||||||
|
How does this work?
|
||||||
|
Let's take a look at the self-contained example
|
||||||
|
(it is way easier than our django implementation, but has the same concept).
|
||||||
|
|
||||||
|
To understand this example you need:
|
||||||
|
1. Be familiar with descriptors: https://docs.python.org/3/howto/descriptor.html
|
||||||
|
2. Follow our explanation bellow
|
||||||
|
|
||||||
|
Let's start with defining our fake model class and fake integer field.
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
from typing import Generic, Union
|
||||||
|
|
||||||
|
class Model(object):
|
||||||
|
...
|
||||||
|
|
||||||
|
_SetType = Union[int, float] # You can assign ints and floats
|
||||||
|
_GetType = int # access type is always `int`
|
||||||
|
|
||||||
|
class IntField(object):
|
||||||
|
def __get__(self, instance: Model, owner) -> _GetType:
|
||||||
|
...
|
||||||
|
|
||||||
|
def __set__(self, instance, value: _SetType) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
|
Now, let's create our own example model,
|
||||||
|
this would be something like ``User`` in your own apps:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
class Example(Model):
|
||||||
|
count = IntField()
|
||||||
|
|
||||||
|
And now, lets test that our reveal type works:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
example = Example()
|
||||||
|
reveal_type(example.count)
|
||||||
|
# Revealed type is "builtins.int"
|
||||||
|
|
||||||
|
example.count = 1.5 # ok
|
||||||
|
example.count = 'a'
|
||||||
|
# Incompatible types in assignment
|
||||||
|
# (expression has type "str", variable has type "Union[int, float]")
|
||||||
|
|
||||||
|
Notice, that this is not magic. This is how descriptors work with ``mypy``.
|
||||||
|
|
||||||
|
We also need ``_pyi_private_set_type`` attributes
|
||||||
|
and friends to help inside our plugin.
|
||||||
|
It is required to enhance parts like ``filter`` queries.
|
||||||
|
"""
|
||||||
|
|
||||||
_pyi_private_set_type: Any
|
_pyi_private_set_type: Any
|
||||||
_pyi_private_get_type: Any
|
_pyi_private_get_type: Any
|
||||||
_pyi_lookup_exact_type: Any
|
_pyi_lookup_exact_type: Any
|
||||||
|
|||||||
Reference in New Issue
Block a user