2017-11-25 9 views
0

私は参考文献や例を見ていますが、まだこの権利を得ることはできません。Python 3/Djangoでメタクラスを正しく使う

Djangoは、渡された値に固有のあらゆる種類のメソッドなどを作成するファクトリシステムの一部としてメタクラスを使用する例がたくさんあります。アイデアは明らかです。しかし、それが本当にどのように動作するのはちょっと不思議です。

ジャンゴ(ストレートジャンゴ「入門」チュートリアルからの)コードの代表的な作品は、次のようになります。

from django.db import models 

class Question(models.Model): 
    question_text = models.CharField(max_length=200) 
    pub_date = models.DateTimeField('date published') 


class Choice(models.Model): 
    question = models.ForeignKey(Question, on_delete=models.CASCADE) 
    choice_text = models.CharField(max_length=200) 
    votes = models.IntegerField(default=0) 

、後に、例えば、これらのクラスの実際のインスタンスが存在します。

q1 = Question(question_text='my question', pub_date='01-01-2017') 

しかし、クラス定義内のquestion_textとpub_dataは、それらがクラス全体のオブジェクト(つまり、q1、q2などのそのクラスのすべてのインスタンスによって共有されている)のように見えます。

クラスDEFはのように見えたように、この操作を行うとの分離を維持するために、より多くの伝統的な方法は、それぞれの前に「自己」が存在することは、次のようになります。

class Question(models.Model): 
    self.question_text = models.CharField(max_length=200) 
    self.pub_date = models.DateTimeField('date published') 

私も見てみましたDjangoのソースコード。実際、models.Modelは、モデルに基づいた新しいクラスが宣言されるたびに呼び出されるメタクラスをその上に持つクラスです.Model。しかし、このコードはかなりわかりにくいです。

ここで何か慣れているのですか?私はクラスで宣言された変数がインスタンス間で共有されることを意図していないと推測します。おそらく、私はヴァルス(とあなたのタイプ、もしそうならば)を宣言するのは、単純にそれらを内部属性dictに押し込む方法であり、メタクラスはある種の魔法を実行して結果をもたらすそれはより論理的なようです。

しかし、どういうわけか、コードが一緒になり、同様に1が別のインスタンスを作成して:彼らはいるかのように、ACRようにあなたは、q1.question_textまたはq2.pub_dateを参照する場合、デモ・コードが正常に動作します

q2 = Question(question_text='my next question', pub_date='01-02-2017') 

クラス宣言で宣言された変数は、実際には、「自己」を持っていました。予め保留されている。

、ここではDjangoのソースは(モデルがライン383とその上のメタclasssである)好奇心の場合:https://github.com/django/django/blob/master/django/db/models/base.py

答えて

2

フィールド、DBスキーマ内の列の表現を意味し、クラス - ですレベルですが、値はインスタンスレベルです。

は、あなたがIntegerFieldとを持っていると言う:

class WithInt(models.Model): 
    fld = models.IntegerField() 

これは意味:

type(WithInt.fld) # IntegerField 
inst = WithInt.objects.get(1) 
type(inst.fld) # int 
+0

をSO、以下の二つのことは本当ですか? (1)クラス全体のvar fldはデータベース値ではなく、どのモデルに依存するかについての記述を持ちます.IntegerFieldは/です(例えば、型記述子だけでなく、データベーステーブルを指すこともできますフィールド、または何でも)。 (2)WithIntクラスのインスタンスは、プライベートフィールド(self.fld)を持ちます。これは整数ですか?私は、これがすべて真実ならば、メタクラスはself.xxx属性を正しいdicts /構造体に置くという汚い作業をしていると推測していますか? – eSurfsnake

+0

それは正しいことです。メタクラスはその背後にあるすべてのことをします。 – cwallenpoole

+0

ありがとう - 舞台裏で起こっていることのすべてを理解するのは簡単ではありません。 – eSurfsnake

関連する問題