sbdchd / django-types

:doughnut: Type stubs for Django
MIT License
202 stars 63 forks source link

"Model" has no attribute "_meta" #84

Closed yoav-orca closed 1 year ago

yoav-orca commented 2 years ago

I'm still working on going off mypy plugin, and I got into a new issue

from django.db.models import Model

if Model._meta.app_label == "app":  # this works
    pass

if Model()._meta.app_label == "app":  # error: "Model" has no attribute "_meta"
    pass
sbdchd commented 2 years ago

Hmm something is wrong with the types in: https://github.com/sbdchd/django-types/blob/946c286cf0b0197f2253f1aeb403f8a8dc9139ff/django-stubs/db/models/base.pyi#L34-L44

Maybe it needs to be a normal property instead of a class property?

yoav-orca commented 2 years ago

Mypy is right here, the instance of the class Model doesn't have the property _meta. Here's a reproduction in non-django code:

from typing import Optional

class Meta(type):
    @property
    def meta(cls) -> Optional[int]:
        return None

class MyClass(metaclass=Meta):
    pass

print(MyClass.meta)
print(MyClass().meta)  # 'MyClass' object has no attribute 'meta'
last-partizan commented 2 years ago

This is a bit strange, documentation mentions only MyClass._meta https://docs.djangoproject.com/en/4.0/ref/models/meta/

But in reality instance._meta works too.

last-partizan commented 1 year ago

I was using type(instance)._meta in my code, but turns out it isn't safe alternative.

Sometimes, when i get object wrapped in SimpleLazyObject, it will return SimpleLazyObject as type, and it won't have _meta. But, instance._meta works well.