Получить поля модели в Джанго - PullRequest
100 голосов
/ 06 сентября 2010

Учитывая модель Django, я пытаюсь перечислить все ее поля. Я видел несколько примеров такого использования атрибута модели _meta, но разве подчеркивание перед мета не указывает на то, что атрибут _meta является закрытым атрибутом и к нему нельзя обращаться напрямую? ... Потому что, например, макет _meta может измениться в будущем и не будет стабильным API?

Является ли _meta исключением из этого правила? Он стабилен и готов к использованию или считается плохой практикой для доступа к нему? Или есть функция или какой-то другой способ для анализа полей модели без использования атрибута _meta? Ниже приведен список некоторых ссылок, показывающих, как это сделать с помощью атрибута _meta

Любой совет очень ценится.

поле получения / установки объекта django

http://www.djangofoo.com/80/get-list-model-fields

Как исследовать поля модели Django?

Ответы [ 9 ]

132 голосов
/ 06 сентября 2010

_meta закрытый, но относительно стабильный.Есть попытки формализовать это, задокументировать и удалить подчеркивание, что может произойти до 1.3 или 1.4.Я полагаю, что будут предприняты усилия для обеспечения обратной совместимости, потому что многие люди все равно его используют.

Если вас особенно беспокоит совместимость, напишите функцию, которая берет модель и возвращает поля.Это означает, что если что-то изменится в будущем, вам нужно будет изменить только одну функцию.

def get_model_fields(model):
    return model._meta.fields

Я считаю, что это вернет список Field объектов.Чтобы получить значение каждого поля из экземпляра, используйте getattr(instance, field.name).

Обновление: участники Django работают над API, чтобы заменить объект _Meta как часть Google Summer of Code.См .:
- https://groups.google.com/forum/#!topic/django-developers/hD4roZq0wyk
- https://code.djangoproject.com/wiki/new_meta_api

82 голосов
/ 03 апреля 2015

Я знаю, что этот пост довольно старый, но я просто хотел сказать всем, кто ищет то же самое, что для этого есть открытый и официальный API: get_fields() и get_field()

Использование:

fields = model._meta.get_fields()
my_field = model._meta.get_field('my_field')

https://docs.djangoproject.com/en/1.8/ref/models/meta/

8 голосов
/ 16 января 2013

Это то, что делает сам Джанго при создании формы из модели.Он использует атрибут _meta, но, как отметил Бернхард, он использует и _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)
6 голосов
/ 01 декабря 2016

Теперь есть специальный метод - get_fields ()

    >>> from django.contrib.auth.models import User
    >>> User._meta.get_fields()

Принимает два параметра, которые можно использовать для управления возвращаемыми полями:

  • include_parents

    True по умолчанию. Рекурсивно включает в себя поля, определенные в родительских классах. Если установлено значение False, get_fields () будет искать только поля, объявленные непосредственно в текущей модели. Поля из моделей, которые непосредственно наследуются от абстрактных моделей или прокси-классов, считаются локальными, а не родительскими.

  • include_hidden

    Ложь по умолчанию. Если установлено значение True, get_fields () будет включать поля, которые используются для поддержки функциональности других полей. Это также будет включать в себя любые поля, имеющие related_name (например, ManyToManyField или ForeignKey), которые начинаются с «+»

4 голосов
/ 31 июля 2018

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']
4 голосов
/ 09 декабря 2013

Поля модели, содержащиеся в _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.)

2 голосов
/ 03 августа 2016

Как насчет этого.

fields = Model._meta.fields
1 голос
/ 07 апреля 2019

Согласно документации Django 2.2 вы можете использовать:

Чтобы получить все поля: Model._meta.get_fields()

Чтобы получить отдельное поле: Model._meta.get_field('field name')

ех. Session._meta.get_field('expire_date')

0 голосов
/ 16 января 2019

Если это необходимо для вашего 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
        ...
...