Adds docs for how Field access works

This commit is contained in:
sobolevn
2021-06-23 13:43:40 +03:00
parent eb702384a8
commit 159a0e4790

View File

@@ -43,6 +43,64 @@ _ST = TypeVar("_ST", contravariant=True)
_GT = TypeVar("_GT", covariant=True)
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_get_type: Any
_pyi_lookup_exact_type: Any