DjangoのMetaクラスはどのように機能しますか?


189

私はDjangoを使用しています。Djangoを使用すると、クラスにパラメータを追加できますclass Meta

class FooModel(models.Model):
    ...
    class Meta:
        ...

私がPythonのドキュメントで見つけた唯一のものは:

class FooMetaClass(type):
    ...

class FooClass:
    __metaclass__ = FooMetaClass

しかし、これは同じことだとは思いません。


6
タイトルはPythonメタについて尋ねますが、質問ではDjangoメタについて尋ねているようです-あなたは何を尋ねていますか?
ckhan 2012

10
@ckhan彼は、ネストされたクラス「Meta」を呼び出すという不条理な決定(IMO)のために混乱しています。初心者向け、Pythonのメタクラスについて、そしてそれを
初めて

回答:


231

次の2つのことについて質問しています。

  1. MetaDjangoモデルの内部クラス

    これは、モデルにアタッチされたいくつかのオプション(メタデータ)を持つ単なるクラスコンテナーです。利用可能な権限、関連するデータベーステーブル名、モデルが抽象かどうか、名前の単数形と複数形などを定義します。

    簡単な説明はこちら:Djangoドキュメント:モデル:メタオプション

    利用可能なメタオプションのリストはここにあります:Djangoドキュメント:モデルメタオプション

    Djangoの最新バージョンの場合:Django docs:モデルメタオプション

  2. Pythonのメタクラス

    最良の説明はこちらです:Pythonのメタクラスとは何ですか?


3
これら2つはまったく関連していますか?つまり、DjangoのMeta内部クラスにより、Pythonの組み込みメタクラス機能を使用できなくなりますか?
nnyby

10
@nnyby:これら2つの概念の間の関係を作成する2つの事柄があります:多くのユーザーが持っている名前と混乱(OPは元の質問でそれを持っているので)。よくある混乱に対処することは、このtopiの大きな利点であると私は信じています。同意しない?
Tadeck 2015

48

上記のTadeckのDjangoの回答を拡張して、Djangoでの「クラスメタ:」の使用も、通常のPythonにすぎません。

内部クラスは、クラスインスタンス間で共有されるデータの便利な名前空間です(したがって、「メタデータ」の名前はメタですが、好きな名前を付けることができます)。Djangoでは一般的に読み取り専用の設定ですが、変更を止めることはできません。

In [1]: class Foo(object):
   ...:     class Meta:
   ...:         metaVal = 1
   ...:         
In [2]: f1 = Foo()
In [3]: f2 = Foo()
In [4]: f1.Meta.metaVal
Out[4]: 1
In [5]: f2.Meta.metaVal = 2
In [6]: f1.Meta.metaVal
Out[6]: 2
In [7]: Foo.Meta.metaVal
Out[7]: 2

Djangoで直接探索することもできます。例:

In [1]: from django.contrib.auth.models import User
In [2]: User.Meta
Out[2]: django.contrib.auth.models.Meta
In [3]: User.Meta.__dict__
Out[3]: 
{'__doc__': None,
 '__module__': 'django.contrib.auth.models',
 'abstract': False,
 'verbose_name': <django.utils.functional.__proxy__ at 0x26a6610>,
 'verbose_name_plural': <django.utils.functional.__proxy__ at 0x26a6650>}

ただし、Djangoでは、モデルの作成時にモデルによって作成され_metaOptionsオブジェクトである属性を探索する可能性が高くなりますmetaclass。ここに、Djangoクラスのすべての「メタ」情報が表示されます。DjangoではMeta_meta Optionsオブジェクトを作成するプロセスに情報を渡すためだけに使用されます。


これはユーザー定義モデルでは機能しません:>>> from myapp.models import MyModel >>> MyModel.Meta Traceback(last the last call last):File "<console>"、line 1、in <module> AttributeError:タイプオブジェクト 'MyModel'には属性 'meta'がありません
bdf

2
たとえば、アンダースコアが必要ですMyUser.objects.get(pk=1)._meta
Paul Whipp、2015

そうですが、モデルのクラスの内部メタクラスにはアクセスしません。これは、そのモデルのインスタンスの_metaオプションにアクセスします...内部のMetaクラス自体にアクセスする方法のようには見えません。私の使用例は、MyModelProxyがMyModelの内部Metaクラスを継承できるように、MyModelからプロキシMyModelProxyクラスをサブクラス化することでした。
bdf

モデルの「内部type(MyUser.objects.get(pk=1)).Meta
Paul

2
「クラスのインスタンス間で共有されるデータのための便利な名前空間」その行は私のためにそれをしました。
MGP

22

DjangoのModelクラスは特にMeta、クラスという名前の属性を持つことを処理します。Pythonの一般的なことではありません。

Pythonメタクラスは完全に異なります。


12
あなたの答えは十分に明確ではないと思います- Metaクラスがどのように機能するかについて詳しく教えてもらえますか?OPがそれについて具体的に尋ねたと思います。
-Tadeck

6

DjangoモデルMetaとメタクラスが「完全に異なる」と主張する回答は、誤解を招く回答です。

Djangoモデルクラスオブジェクト(つまり、クラス定義自体を表すオブジェクトです。はい、クラスもオブジェクトです)の構築は、というメタクラスによって実際に制御されています。ModelBaseそのコードは次のとおりです。

https://github.com/django/django/blob/master/django/db/models/base.py#L61

そして、実行することの1つは、検証機構、フィールドの詳細、保存ロジックなどを含むすべてのDjangoモデルに属性ModelBaseを作成すること_metaです。この操作中に、モデルの内部Metaクラスで指定されたものが読み込まれ、そのプロセス内で使用されます。

したがって、はい、ある意味Metaではメタクラスは異なる「もの」ですが、Djangoモデル構築のメカニズム内では、それらは密接に関連しています。それらがどのように連携するかを理解することで、両方に対する洞察を一度に深めることができます。

これは、Djangoモデルがメタクラスをどのように使用するかを理解するのに役立つ情報源になる可能性があります。

https://code.djangoproject.com/wiki/DevModelCreation

そして、これはオブジェクトが一般的にどのように機能するかをよりよく理解したい場合にも役立ちます。

https://docs.python.org/3/reference/datamodel.html


0

内部メタクラスドキュメントこのdjangoモデルメタデータのドキュメントは、順序付けオプション(ordering)、データベーステーブル名(db_table)、人間が読める単数形および複数形の名前(verbose_nameおよびverbose_name_plural)など、「フィールドではないもの」です。必要なものはなく、モデルへのクラスMetaの追加は完全にオプションです。 https://docs.djangoproject.com/en/dev/topics/db/models/#meta-options


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.