I'm having an issue with developing something similar to the Django _get_queryset(klass) method. I'm trying to pull a QuerySet when provided with either a QuerySet, or a mongoengine Document. I've tried the following logic:
from mongoengine.base import BaseDocument
from mongoengine.queryset import QuerySet
def _get_queryset(klass):
if isinstance(klass, QuerySet):
return klass
if isinstance(klass, BaseDocument):
return klass.objects
else:
raise ValueError
For a given Document, such as:
class Monkey(mongoengine.Document):
name = mongoengine.StringField(unique=True)
If I pass the following in to python's is_instance()
>>> isinstance(db.Monkey.objects, QuerySet)
True
But (seemingly) surprisingly,
>>> isinstance(Monkey, BaseDocument)
False
>>> isinstance(Monkey(), BaseDocument)
True
Does isinstance()
not instantiate the class when presented with it? In Django, a roughly equivalent call works:
>>> isinstance(Monkey, ModelBase)
True
Why does Monkey
get instantiated here in Django, but not in the above mongoengine version?
In python classes are objects. In particular they are instances of type
:
>>> class MyClass(object): pass
...
>>> isinstance(MyClass, type)
True
Also, since object
is the most base-type they are also instances of object
:
>>> isinstance(MyClass, object)
True
so, the result you are obtaining is correct. An instance of a class is something different from the class itself. If you want to check whether a class is a subclass, there is the issubclass
function:
>>> issubclass(MyClass, object)
True
The fact that in Django isinstance(Monkey, ModelBase)
works is because in django ModelBase
is not a class but a metaclass:
# from django source-code
class ModelBase(type):
"""
Metaclass for all models.
"""
Which means that model classes are instances of their metaclass(in this case ModelBase
).
In Python, classes themselves are objects. By default, a class is of type type
(ie it is an instance of the type
class), but that default can be overridden by using a metaclass . Using a metaclass will cause the class to be an instance of the metaclass (which should extend type
).
This means that if you define a class Monkey
with metaclass ModelBase
, then Python will create a ModelBase
object named Monkey
. The Monkey
object is a class, so you can instantiate objects of type Monkey
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.