について非常に基本的な質問がありdjango.db.models
ます。
この公式の django チュートリアルで単語 " " を検索するchoice_set
と、変数 " choice_set
" がどこにも宣言されていないことがわかりますが、魔法のように、コードで使用を開始できます。
*_set 変数を魔法のように作成したものはdjango.db.models.Model
何をするのでしょうか? また、他にどのような変数を作成するのでしょうか?
について非常に基本的な質問がありdjango.db.models
ます。
この公式の django チュートリアルで単語 " " を検索するchoice_set
と、変数 " choice_set
" がどこにも宣言されていないことがわかりますが、魔法のように、コードで使用を開始できます。
*_set 変数を魔法のように作成したものはdjango.db.models.Model
何をするのでしょうか? また、他にどのような変数を作成するのでしょうか?
dir
関数を使用して、定義した属性と定義された属性の両方のクラスの属性の完全なリストを取得できます。
dir(Poll)
あなたは少し似たものになるでしょう(正確ではありませんが、私は回り道でそれを構築しています):
['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__',
'__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__',
'__init__', '__metaclass__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__',
'__weakref__', '_base_manager', '_default_manager', '_deferred', '_get_FIELD_display',
'_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', '_get_pk_val',
'_get_unique_checks', '_meta', '_perform_date_checks', '_perform_unique_checks', '_set_pk_val',
'clean', 'clean_fields', 'curve_set', 'date_error_message', 'delete', 'full_clean', 'objects',
'pk', 'prepare_database_save', 'save', 'save_base', 'choice_set',
'serializable_value', 'unique_error_message', 'validate_unique']
それは多くの価値です!DoesNotExist
やのような例外MultipleObjectsReturned
と、最も重要なobjects
. しかし、これらの属性のいくつかは Django によって追加されませんでした。そうすれば、すべてのオブジェクトdir(object())
の属性のリストが見つかります:
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
ほとんどの場合、 two で始まり 2 で終わるものは無視できます__
。他のほとんどは Django によって追加されました。
これらを実際に設定する方法と場所について: Django はmodels.Model
メタクラスを使用して、各新しいモデルの属性のほとんどを動的に設定します。最初に知っておくべきことは、次のsetattr
関数を使用して、クラスにメンバーまたはメソッドを動的に追加できることです。
class X:
pass
setattr(X, "q", 12)
print X.q # prints 12
これが、属性の名前に基づいて新しい属性を作成する方法です。
チュートリアルでは、これらの追加属性の定義を開始できるようにする重要な行は次のとおりです。
class Poll(models.Model):
これは、クラスが (Django に属する)Poll
クラスを継承することを意味します。models.Model
継承には多くの便利なプロパティがあります。基本的に、Poll
クラスはクラスが設定した動作の一部を継承しmodels.Model
ますが、これらの新しい属性のほとんどを定義する場所は Modelメタクラスです。メタクラスは難しい概念ですが、基本的には新しいクラスを作成するためのレシピとして機能し、メタクラスを定義することで、Django はmodels.py
メタクラスが定義されているときに介入し、新しい を定義します。
Model メタクラスのコードは、ここ(55 行目から) にあります。これは、実際にゼロからクラスを段階的に作成する一連のコードです。見た目は複雑ですが、変数名を見るだけで多くのことがわかります。たとえば、有望な名前のadd_to_class
メソッドを見てください。
def add_to_class(cls, name, value):
if hasattr(value, 'contribute_to_class'):
value.contribute_to_class(cls, name)
else:
setattr(cls, name, value)
'contribute_to_class
(重要ではない)の 1 つの特殊なケースを除けば、これは新しい属性 (メソッドやメンバーなど) をクラスに追加するためのメソッドです。それが呼び出された場所は、それが追加しているもののヒントを与えてくれます:
class.add_to_class('DoesNotExist', subclass_exception(str('DoesNotExist') ...<truncated>...
ここでは例外を追加しています。これは、存在しないDoesNotExist
を要求した場合に返されるものです。Poll
( を実行Poll.objects.get(pk=1337)
するか、直接入力して確認してくださいPoll.DoesNotExist
)。
しかし、実際には Django はそれよりもさらに複雑です。あなたが求めている特定 の属性は、すべてのモデルに対して構築されるわけではありません-フィールドが a によって別のフィールドに関連付けられたときに作成されます (あなたのとのように)。割り当てられるさまざまな場所は非常に複雑ですが、基本的にはすべてrelated.pyのこの関数に戻ります。_set
ForeignKey
Poll
Choice
get_accessor_name
def get_accessor_name(self):
# This method encapsulates the logic that decides what name to give an
# accessor descriptor that retrieves related many-to-one or
# many-to-many objects. It uses the lower-cased object_name + "_set",
# but this can be overridden with the "related_name" option.
if self.field.rel.multiple:
# If this is a symmetrical m2m relation on self, there is no reverse accessor.
if getattr(self.field.rel, 'symmetrical', False) and self.model == self.parent_model:
return None
return self.field.rel.related_name or (self.opts.object_name.lower() + '_set')
else:
return self.field.rel.related_name or (self.opts.object_name.lower())
それはちょうど名前を思いついたところです。それをさかのぼって、それがどのようにクラスに追加されたかを理解することは簡単なことではありません。しかし、このことから、Django にはこのような属性を追加する機会がたくさんあることがわかると思います。
これはいくつかのForeignKey
魔法です:)
Choice
モデルには、オブジェクトに対する属性poll
である があります。Django はオブジェクトに便利なメソッドを追加します。これにより、そのオブジェクトを参照するすべてのオブジェクトを含む が提供されます。ForeignKey
Poll
choice_set
Poll
QuerySet
Choice
Poll
したがって、この(疑似)コードを考えると
myPoll = Poll(question='Is Django awesome?')
option_yes = Choice(poll=myPoll, choice='Yes')
option_no = Choice(poll=myPoll, choice='No')
後で実行できます
poll = Poll.objects.get(question='Is Django awesome?')
options = poll.choice_set.all()
オプションには、関連するChoice
オブジェクトが含まれます。
related_name
を定義するときにオプションを使用して、この属性の名前を変更できますForeignKey
。