0

Django _get_queryset(klass)メソッドに似たものの開発に問題があります。QuerySetまたはmongoengine Documentのいずれかが提供されている場合、QuerySetをプルしようとしています。私は次のロジックを試しました:

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

次のような特定のドキュメントの場合:

class Monkey(mongoengine.Document):
    name = mongoengine.StringField(unique=True)

以下をpythonのに渡すとis_instance()

>>> isinstance(db.Monkey.objects, QuerySet)
True

しかし(一見)驚くべきことに、

>>> isinstance(Monkey, BaseDocument)
False

>>> isinstance(Monkey(), BaseDocument)
True

isinstance()提示されたときにクラスをインスタンス化しませんか? Django では、ほぼ同等の呼び出しが機能します。

>>> isinstance(Monkey, ModelBase)
True

Monkeyここで Django ではインスタンス化されるのに、上記の mongoengine バージョンではインスタンス化されないのはなぜですか?

4

2 に答える 2

3

Python では、クラスはオブジェクトです。特に、それらは次のインスタンスですtype

>>> class MyClass(object): pass
... 
>>> isinstance(MyClass, type)
True

また、objectは最も基本的な型であるため、次のインスタンスでもありますobject

>>> isinstance(MyClass, object)
True

したがって、取得している結果は正しいです。クラスのインスタンスは、クラス自体とは別のものです。クラスがサブクラスかどうかを確認したい場合は、次のissubclass関数があります。

>>> issubclass(MyClass, object)
True

Django で機能するという事実isinstance(Monkey, ModelBase)は、djangoModelBaseではクラスではなくメタクラスであるためです。

# from django source-code
class ModelBase(type):
    """
    Metaclass for all models.
    """

つまり、モデル クラスはそのメタクラス (この場合はModelBase) のインスタンスです。

于 2013-03-10T12:50:57.453 に答える
1

Pythonでは、クラス自体がオブジェクトです。デフォルトでは、クラスはタイプtype(つまり、クラスのインスタンス)ですが、そのデフォルトは、メタクラスtypeを使用してオーバーライドできます。メタクラスを使用すると、クラスはメタクラスのインスタンスになります(拡張する必要があります)。type

これは、Monkeyメタクラスを使用してクラスを定義するModelBaseと、Pythonが。ModelBaseという名前のオブジェクトを作成することを意味しますMonkey。オブジェクトはクラスであるため、タイプがのMonkeyオブジェクトをインスタンス化できますMonkey

于 2013-03-10T13:01:21.480 に答える