admin管理员组文章数量:1125077
I need help with type hint for a custom model manager method.
This is my custom manager and a base model. I inherit this base model to other models so that I don't have to write common fields again and again.
class BaseManager(models.Manager):
def get_or_none(self, *args, **kwargs):
try:
return self.get(*args, **kwargs)
except self.model.DoesNotExist:
return None
class BaseModel(models.Model):
id = models.UUIDField(
primary_key=True, default=uuid.uuid4, verbose_name="ID", editable=False
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = BaseManager() # Set the custom manager
class Meta:
abstract = True
This is an example model:
class MyModel(BaseModel):
category = models.CharField(max_length=10)
Now for this:
my_object = MyModel.objects.get_or_none(
category="...",
)
The type annotation is like this when I hover in my IDE:
my_object: BaseModel | None = MyModel.objects. get_or_none(...
But I want the type annotation like this:
my_object: MyModel | None = MyModel.objects. get_or_none(...
How can I do that? This works for the default methods like get and filter. But how to do this for custom methods like get_or_none?
Please help me.
Thanks
I need help with type hint for a custom model manager method.
This is my custom manager and a base model. I inherit this base model to other models so that I don't have to write common fields again and again.
class BaseManager(models.Manager):
def get_or_none(self, *args, **kwargs):
try:
return self.get(*args, **kwargs)
except self.model.DoesNotExist:
return None
class BaseModel(models.Model):
id = models.UUIDField(
primary_key=True, default=uuid.uuid4, verbose_name="ID", editable=False
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = BaseManager() # Set the custom manager
class Meta:
abstract = True
This is an example model:
class MyModel(BaseModel):
category = models.CharField(max_length=10)
Now for this:
my_object = MyModel.objects.get_or_none(
category="...",
)
The type annotation is like this when I hover in my IDE:
my_object: BaseModel | None = MyModel.objects. get_or_none(...
But I want the type annotation like this:
my_object: MyModel | None = MyModel.objects. get_or_none(...
How can I do that? This works for the default methods like get and filter. But how to do this for custom methods like get_or_none?
Please help me.
Thanks
Share Improve this question asked 2 days ago Nahidujjaman HridoyNahidujjaman Hridoy 2,2073 gold badges17 silver badges35 bronze badges 2 |2 Answers
Reset to default 0Python's type inference system can not interfere this, because the code works a bit too much with meta-programming, etc. and the interpreter can not "get through" that (yet). For example a package like django-stubs
[GitHub] contains type hints that help the type checker to understand the types.
This then looks like [GitHub]:
from typing_extensions import Self class Model(metaclass=ModelBase): # … objects: ClassVar[Manager[Self]]
If you enable Django support in PyCharm, PyCharm will normally install django-stubs
behind the curtains to help you with these type checks.
They thus rewrote the Manager
type to make sure one can subscript it with the type of the model the manager deals with.
You can add a .pyi
file that drops the hint with:
# path/to/base/manager.pyi
from typing import Generic, Tuple, TypeVar
from django.db.models.base import Model
from django.db.models.manager import Manager
_T = TypeVar('_T', bound=Model, covariant=True)
class BaseManager(Generic[_T], Manager[_T]):
def get_or_none(self, *args, **kwargs) -> _T | None: …
and ensure that _T
contains a reference to the model with:
# path/to/base/model.pyi
from typing import ClassVar
from django.db.models.base import Model
from path.to.base.manager import BaseManager
from typing_extensions import Self
class BaseModel(Model):
objects: ClassVar[OrderHistoryManager[Self]]
Normally PyCharm will then pick up the type hints.
In order for your IDE to see get_or_none
method, You should add type annotation to objects
variable in your BaseModel
class like so:
objects: BaseManager = BaseManager()
本文标签: pythonDynamic type annotation for Django model managers custom methodStack Overflow
版权声明:本文标题:python - Dynamic type annotation for Django model managers custom method - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736655667a1946246.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
django-stubs
or some other typing library, because by default Python's type system could not interfere that for.get
either. – willeM_ Van Onsem Commented 2 days ago