21

だから私はこのようなDjangoモデルを作成することができます:

from django.db import models

class Something(models.Model):
    title = models.TextField(max_length=200)

そして私はこのようにそれを扱うことができます:

thing = Something()
#set title
thing.title = "First thing"
#get title
thing.title

すべて正常に動作しますが、どのように動作するかを理解したいと思います。

title = models.TextField(max_length=200)

上記の非DjangoPythonコードでは、models.TextField型のクラス変数titleを定義しており、次のようにアクセスすることもできますthing.__class__.title:(リンク

しかし、Djangoで何かのインスタンスを作成すると、突然、テキストを取得/設定できるtitle属性ができました。そして、thing.__class__.titlething.titleを実行するときに明確にアクセスできません。クラス変数「title」にアクセスしていませんが、生成された属性/プロパティにアクセスしていますか?

フィールドがthing._meta.fieldsになってしまったことは知っていますが、どうすればよいでしょうか。何がどのように起こっているのですか?

1、Djangoは舞台裏でプロパティ「タイトル」を作成しますか?

2、クラス変数「title」はどうなりましたか?

4

2 に答える 2

17

Djangoのドキュメントがこれについて述べていることを打ち負かすのは難しいと思います。

Modelクラス(base.pyを参照)には、ModelBase(同じくbase.py内)を新しいクラスの作成に使用するクラスとして定義するメタクラス属性があります。つまり、ModelBase。newは、この新しいExampleクラスを作成するために呼び出されます。ここでは、インスタンスではなく、クラスオブジェクトを作成していることを理解することが重要です。言い換えると、Pythonは、現在の名前空間のExample名に最終的にバインドされるものを作成しています。

基本的に、メタクラスはクラス自体がどのように作成されるかを定義します。作成中に、追加の属性/メソッド/すべてをそのクラスにバインドできます。このstackoverflowの回答の例は、クラスのすべての属性を大文字にしています

# remember that `type` is actually a class like `str` and `int`
# so you can inherit from it
class UpperAttrMetaclass(type): 
    # __new__ is the method called before __init__
    # it's the method that creates the object and returns it
    # while __init__ just initializes the object passed as parameter
    # you rarely use __new__, except when you want to control how the object
    # is created.
    # here the created object is the class, and we want to customize it
    # so we override __new__
    # you can do some stuff in __init__ too if you wish
    # some advanced use involves overriding __call__ as well, but we won't
    # see this
    def __new__(upperattr_metaclass, future_class_name, 
                future_class_parents, future_class_attr):

        attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
        uppercase_attr = dict((name.upper(), value) for name, value in attrs)

        return type(future_class_name, future_class_parents, uppercase_attr)

同様に、モデル用のDjangoのメタクラスは、クラスに適用した属性をダイジェストし、メソッドなどを含む、検証などに役立つさまざまな属性を追加できます。

于 2012-08-17T13:24:01.943 に答える
2

python is extremely powerfull and permit the developer to use intrespection.

django use a lot of metaclass. and it seem that models.Model use it too. see in django\db\models\base.py

class Model(object):
    __metaclass__ = ModelBase

i think the metaclass just take the classes attributes such a the Field and for all new instance for these Model subclass,create the apropriate variable.

1) yes, django create the instance variable of property "title" automaticaly 2) in the same way, the metaclass move the fields into the meta class...

于 2012-08-17T13:49:37.970 に答える