Djangoモデルを考えると、そのすべてのフィールドをリストしようとしています。 _metaモデル属性を使用してこれを行う例を見てきましたが、メタの前にあるアンダースコアは、_meta属性がプライベート属性であり、直接アクセスすべきではないことを示していませんか? ...たとえば、_metaのレイアウトは将来変更される可能性があり、安定したAPIではない可能性がありますか?
_metaはこのルールの例外ですか?安定しており、すぐに使用できますか、またはアクセスするのは悪い習慣と見なされていますか?または、_meta属性を使用せずにモデルのフィールドをイントロスペクトする関数または他の方法がありますか?以下は、_meta属性を使用してこれを行う方法を示すいくつかのリンクのリストです。
どんなアドバイスも大歓迎です。
_meta
はプライベートですが、比較的安定しています。 1.3または1.4より前に発生する可能性のある、形式化、文書化、アンダースコアの削除を行う努力があります。多くの人がとにかくそれを使用しているので、物事に後方互換性があることを保証する努力がなされると思います。
互換性について特に懸念がある場合は、モデルを取得してフィールドを返す関数を作成します。これは、将来何かが変更された場合、1つの機能を変更するだけでよいことを意味します。
def get_model_fields(model):
return model._meta.fields
これにより、Field
オブジェクトのリストが返されると思います。インスタンスから各フィールドの値を取得するには、getattr(instance, field.name)
を使用します。
更新:Django貢献者は、Google Summer of Codeの一部として_Metaオブジェクトを置き換えるAPIに取り組んでいます。見る:
- https://groups.google.com/forum/#!topic/Django-developers/hD4roZq0wyk
- https://code.djangoproject.com/wiki/new_meta_api
私はこの投稿がかなり古いことを知っていますが、同じことを探している人に、これを行うためのパブリックおよび公式APIがあることを伝えたいと思いました:get_fields()
and get_field()
使用法:
fields = model._meta.get_fields()
my_field = model._meta.get_field('my_field')
これは、モデルからフォームを構築するときにDjango自体によって実行されるものです。 _meta属性を使用していますが、Bernhardが述べたように、_meta.fieldsと_meta.many_to_manyの両方を使用します。 Django.forms.models.fields_for_modelを見ると、次のようになります。
opts = model._meta
for f in sorted(opts.fields + opts.many_to_many):
print '%s: %s' % (f.name, f)
現在、特別なメソッドがあります- get_fields()
>>> from Django.contrib.auth.models import User
>>> User._meta.get_fields()
返されるフィールドを制御するために使用できる2つのパラメーターを受け入れます。
include_parents
デフォルトで真。親クラスで定義されたフィールドを再帰的に含みます。 Falseに設定すると、get_fields()は現在のモデルで直接宣言されたフィールドのみを検索します。抽象モデルまたはプロキシクラスから直接継承するモデルのフィールドは、親ではなくローカルと見なされます。
include_hidden
デフォルトではfalse。 Trueに設定すると、get_fields()には、他のフィールドの機能を支援するために使用されるフィールドが含まれます。これには、「+」で始まるrelated_name(ManyToManyField、ForeignKeyなど)を持つフィールドも含まれます。
_metaに含まれるモデルフィールドは、それぞれのフィールドオブジェクトのリストとして複数の場所にリストされます。キーがフィールド名である辞書としてそれらを使用する方が簡単な場合があります。
私の意見では、これはモデルフィールドオブジェクトを収集および整理するための最も冗長で表現力のある方法です。
def get_model_fields(model):
fields = {}
options = model._meta
for field in sorted(options.concrete_fields + options.many_to_many + options.virtual_fields):
fields[field.name] = field
return fields
(Django.forms.models.fields_for_modelの この使用例 を参照してください。)
get_fields()
はTuple
を返し、各要素はModel field
型であり、文字列として直接使用することはできません。したがって、field.name
はフィールド名を返します
my_model_fields = [field.name for field in MyModel._meta.get_fields()]
上記のコードは、すべてのフィールド名を含むリストを返します
例
In [11]: from Django.contrib.auth.models import User
In [12]: User._meta.get_fields()
Out[12]:
(<ManyToOneRel: admin.logentry>,
<Django.db.models.fields.AutoField: id>,
<Django.db.models.fields.CharField: password>,
<Django.db.models.fields.DateTimeField: last_login>,
<Django.db.models.fields.BooleanField: is_superuser>,
<Django.db.models.fields.CharField: username>,
<Django.db.models.fields.CharField: first_name>,
<Django.db.models.fields.CharField: last_name>,
<Django.db.models.fields.EmailField: email>,
<Django.db.models.fields.BooleanField: is_staff>,
<Django.db.models.fields.BooleanField: is_active>,
<Django.db.models.fields.DateTimeField: date_joined>,
<Django.db.models.fields.related.ManyToManyField: groups>,
<Django.db.models.fields.related.ManyToManyField: user_permissions>)
In [13]: [field.name for field in User._meta.get_fields()]
Out[13]:
['logentry',
'id',
'password',
'last_login',
'is_superuser',
'username',
'first_name',
'last_name',
'email',
'is_staff',
'is_active',
'date_joined',
'groups',
'user_permissions']
これはどう。
fields = Model._meta.fields
Django documentation 2.2に従って、次を使用できます。
すべてのフィールドを取得するには:Model._meta.get_fields()
個々のフィールドを取得するには:Model._meta.get_field('field name')
例Session._meta.get_field('expire_date')
adminサイトでこれが必要な場合は、ModelAdmin.get_fields
メソッド( docs )もあります。フィールド名のlist
strings
。
例えば:
class MyModelAdmin(admin.ModelAdmin):
# extending change_view, just as an example
def change_view(self, request, object_id=None, form_url='', extra_context=None):
# get the model field names
field_names = self.get_fields(request)
# use the field names
...