Django: Получить список полей модели?
Я определил класс User
, который (в конечном счете) наследует от models.Model
. Я хочу получить список всех полей, определенных для этой модели. Например, phone_number = CharField(max_length=20)
. В принципе, я хочу получить все, что наследуется от класса Field
.
Я думал, что смогу извлечь их, воспользовавшись inspect.getmembers(model)
, но список, который он возвращает, не содержит ни одного из этих полей. Похоже, что Django уже овладел классом и добавил все его магические атрибуты и убрал то, что на самом деле было определено. Итак... как я могу получить эти поля? Вероятно, у них есть функция для извлечения их для собственных внутренних целей?
Ответы
Ответ 1
Джанго версии 1.8 и позже:
Вы должны использовать get_fields()
:
[f.name for f in MyModel._meta.get_fields()]
Метод get_all_field_names()
устарел, начиная с Django 1.8, и будет удален в 1.10.
Страница документации, ссылка на которую приведена выше, обеспечивает полностью обратно совместимую реализацию get_all_field_names()
, но для большинства целей предыдущий пример должен работать просто отлично.
Джанго версии до 1.8:
model._meta.get_all_field_names()
Это должно делать свое дело.
Это требует фактического экземпляра модели. Если все, что у вас есть, это подкласс django.db.models.Model
, то вам следует вызвать myproject.myapp.models.MyModel._meta.get_all_field_names()
Ответ 2
Метод get_all_related_fields()
, упомянутый здесь, не рекомендуется в версии 1.8. Отныне он get_fields()
.
>> from django.contrib.auth.models import User
>> User._meta.get_fields()
Ответ 3
Я считаю, что это очень удобно для моделей django:
def __iter__(self):
for field_name in self._meta.get_all_field_names():
value = getattr(self, field_name, None)
yield (field_name, value)
Это позволяет:
for field, val in object:
print field, val
Ответ 4
Это трюк. Я тестирую его только в Django 1.7.
your_fields = YourModel._meta.local_fields
your_field_names = [f.name for f in your_fields]
Model._meta.local_fields
не содержит полей много-ко-многим. Вы должны получить их с помощью Model._meta.local_many_to_many
.
Ответ 5
def __iter__(self):
field_names = [f.name for f in self._meta.fields]
for field_name in field_names:
value = getattr(self, field_name, None)
yield (field_name, value)
Это сработало для меня в django==1.11.8
Ответ 6
MyModel._meta.get_all_field_names()
устарела несколько версий назад и удалена в Django 1.10.
Вот обратно совместимое предложение из документов:
from itertools import chain
list(set(chain.from_iterable(
(field.name, field.attname) if hasattr(field, 'attname') else (field.name,)
for field in MyModel._meta.get_fields()
# For complete backwards compatibility, you may want to exclude
# GenericForeignKey from the results.
if not (field.many_to_one and field.related_model is None)
)))
Ответ 7
Неясно, есть ли у вас экземпляр класса или самого класса и пытаетесь извлечь поля, но в любом случае рассмотрите следующий код
Использование экземпляра
instance = User.objects.get(username="foo")
instance.__dict__ # returns a dictionary with all fields and their values
instance.__dict__.keys() # returns a dictionary with all fields
list(instance.__dict__.keys()) # returns list with all fields
Использование класса
User._meta.__dict__.get("fields") # returns the fields
# to get the field names consider looping over the fields and calling __str__()
for field in User._meta.__dict__.get("fields"):
field.__str__() # e.g. 'auth.User.id'
Ответ 8
Просто чтобы добавить, я использую самообъект, это сработало для меня:
[f.name for f in self.model._meta.get_fields()]
Ответ 9
По крайней мере, Django 1.9.9 - версия, которую я сейчас использую, - обратите внимание, что .get_fields()
на самом деле также" считает, что любая иностранная модель является полем, что может быть проблематичным. Скажите, что у вас есть:
class Parent(models.Model):
id = UUIDField(primary_key=True)
class Child(models.Model):
parent = models.ForeignKey(Parent)
Отсюда следует, что
>>> map(lambda field:field.name, Parent._model._meta.get_fields())
['id', 'child']
в то время как, как показано @Rockallite
>>> map(lambda field:field.name, Parent._model._meta.local_fields)
['id']
Ответ 10
Поэтому, прежде чем я нашел этот пост, я успешно нашел, что это работает.
Model._meta.fields
Это работает так же, как
Model._meta.get_fields()
Я не уверен, какая разница в результатах, если таковые имеются. Я запустил этот цикл и получил тот же вывод.
for field in Model._meta.fields:
print(field.name)
Ответ 11
Поскольку большинство ответов устарели, я постараюсь обновить вас в Django 2.2. Здесь posts- ваше приложение (записи, блог, магазин и т.д.)
1) Из ссылки на модель: https://docs.djangoproject.com/en/2.2/ref/models/meta/.
from posts.model import BlogPost
all_fields = BlogPost._meta.fields
#or
all_fields = BlogPost._meta.get_fields()
Обратите внимание, что:
all_fields=BlogPost._meta.get_fields()
Также получит некоторые отношения, которые, например, Вы не можете отобразить в представлении.
Как в моем случае:
Organisation._meta.fields
(<django.db.models.fields.AutoField: id>, <django.db.models.fields.DateField: created>...
а также
Organisation._meta.get_fields()
(<ManyToOneRel: crm.activity>, <django.db.models.fields.AutoField: id>, <django.db.models.fields.DateField: created>...
2) Из экземпляра
from posts.model import BlogPost
bp = BlogPost()
all_fields = BlogPost._meta.fields
3) От родительской модели
Предположим, у нас есть Post как родительская модель, и вы хотите видеть все поля в списке, а родительские поля должны быть доступны только для чтения в режиме редактирования.
from django.contrib import admin
from posts.model import BlogPost
@admin.register(BlogPost)
class BlogPost(admin.ModelAdmin):
all_fields = [f.name for f Organisation._meta.fields]
parent_fields = BlogPost.get_deferred_fields(BlogPost)
list_display = all_fields
read_only = parent_fields
Ответ 12
Почему бы просто не использовать это:
manage.py inspectdb
Пример вывода:
class GuardianUserobjectpermission(models.Model):
id = models.IntegerField(primary_key=True) # AutoField?
object_pk = models.CharField(max_length=255)
content_type = models.ForeignKey(DjangoContentType, models.DO_NOTHING)
permission = models.ForeignKey(AuthPermission, models.DO_NOTHING)
user = models.ForeignKey(CustomUsers, models.DO_NOTHING)
class Meta:
managed = False
db_table = 'guardian_userobjectpermission'
unique_together = (('user', 'permission', 'object_pk'),)