Получить поля модели в Django
Учитывая модель Django, я пытаюсь перечислить все ее поля. Я видел несколько примеров такого использования атрибута модели _meta, но разве подчеркивание перед мета не указывает на то, что атрибут _meta является закрытым атрибутом и к нему нельзя обращаться напрямую?... Потому что, например, макет _meta может измениться в будущем и не будет стабильным API?
_Meta является исключением из этого правила? Он стабилен и готов к использованию или считается плохой практикой для доступа к нему? Или есть функция или какой-то другой способ для анализа полей модели без использования атрибута _meta? Ниже приведен список некоторых ссылок, показывающих, как это сделать с помощью атрибута _meta.
Любой совет высоко ценится.
объект django получить/установить поле
http://www.djangofoo.com/80/get-list-model-fields
Как исследовать поля модели Django?
Ответы
Ответ 1
_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
Ответ 2
Я знаю, что этот пост довольно старый, но мне просто хотелось рассказать всем, кто ищет то же самое, что для этого есть публичный и официальный 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/
Ответ 3
Это то, что делает сам Django при создании формы из модели. Он использует атрибут _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)
Ответ 4
Теперь есть специальный метод - get_fields()
>>> from django.contrib.auth.models import User
>>> User._meta.get_fields()
Он принимает два параметра, которые можно использовать для управления возвращаемыми полями:
-
include_parents
Правда по умолчанию. Рекурсивно включает в себя поля, определенные в родительских классах. Если установлено значение False, get_fields() будет искать только поля, объявленные непосредственно в текущей модели. Поля из моделей, которые напрямую наследуются от абстрактных моделей или прокси-классов, считаются локальными, а не родительскими.
-
include_hidden
Ложь по умолчанию. Если установлено значение True, get_fields() будет включать поля, которые используются для поддержки функциональности других полей. Это также будет включать в себя любые поля, имеющие related_name (например, ManyToManyField или ForeignKey), которые начинаются с "+"
Ответ 5
Поля модели, содержащиеся в _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.)
Ответ 6
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']
Ответ 7
Как насчет этого.
fields = Model._meta.fields
Ответ 8
Согласно документации Django 2.2 вы можете использовать:
Чтобы получить все поля: Model._meta.get_fields()
Чтобы получить отдельное поле: Model._meta.get_field('field name')
ех. Session._meta.get_field('expire_date')
Ответ 9
Если вам это нужно для вашего сайта администратора, есть также метод 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
...
Ответ 10
Другой способ - добавить функции в модель, и когда вы хотите переопределить дату, вы можете вызвать функцию.
class MyModel(models.Model):
name = models.CharField(max_length=256)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
def set_created_date(self, created_date):
field = self._meta.get_field('created')
field.auto_now_add = False
self.created = created_date
def set_modified_date(self, modified_date):
field = self._meta.get_field('modified')
field.auto_now = False
self.modified = modified_date
my_model = MyModel(name='test')
my_model.set_modified_date(new_date)
my_model.set_created_date(new_date)
my_model.save()