У меня есть куча тегов включения шаблонов Django, которые принимают в качестве аргумента либо конкретный экземпляр объекта базы данных, либо строку / int, которая интерпретируется как первичный ключ этого объекта базы данных. Например ...
{% render_product product=obj %}
{% render_product product=42 %}
{% render_product product="42" %}
... все работают нормально и делают очевидное: они визуализируют фрагмент шаблона с конкретным экземпляром Product, выбирая его по первичному ключу из базы данных, если это необходимо. Вот как определяются класс Product и похожие классы:
class Product(models.Model):
# standard django model definition goes here
Вот что обычно происходит с таким тегом включения:
@register.inclusion_tag("render_product.html")
def render_product(product: Union[Product, str, int] = None) -> dict:
_product = None
if isinstance(product, Product):
_product = product
elif isinstance(product, str) or isinstance(product, int):
try:
_product = Product.objects.get(pk=product)
except (Product.DoesNotExist, ValueError):
pass
return {"product": _product}
Поскольку в десятках тегов включения у меня одна и та же схема, я пытаюсь ее реорганизовать, чтобы у меня было что-то вроде:
@register.inclusion_tag("render_product.html")
def render_product(product: Union[Product, str, int] = None) -> dict:
_product = fetch_object(Product, product)
return {"product": _product}
Вот код fetch_object:
def fetch_object(cls: Type[Model] = None, obj: Union[Model, str, int] = None):
if isinstance(obj, cls):
return obj
elif isinstance(obj, str) or isinstance(obj, int):
try:
return cls.objects.get(pk=obj)
except (cls.DoesNotExist, ValueError):
pass
return None
Моя проблема: я понятия не имею, как указать тип возвращаемого значения этой функции. По сути, это должно быть что-то вроде «экземпляра любого класса, производного от Model или None». Но если я попробую что-то вроде ...
def fetch_object(
cls: Type[Model] = None, obj: Union[Model, str, int] = None
) -> Union[Model, None]:
... тогда PyCharm жалуется на «неразрешенную ссылку на атрибут», если я получаю доступ к методу извлеченного объекта, который зависит от продукта, а не от модели.
Я пытаюсь использовать все больше и больше подсказок в моем коде Python, потому что это уже несколько раз спасло мою задницу, но это один из тех случаев, когда я понятия не имею, как правильно поступить это было бы, и мое Google-фу подводит меня.
Как правильно указывать тип для fetch_object?