Django: получить список полей модели?
я определил User
класс, который (в конечном счете) наследует от models.Model
. Я хочу получить список всех полей, определенных для этой модели. Например, phone_number = CharField(max_length=20)
. В принципе, я хочу получить все, что наследуется от Field
класса.
Я думал, что смогу получить их, воспользовавшись inspect.getmembers(model)
, но он возвращает список не содержит ни одного из этих полей. Похоже, что Django уже завладел классом и добавил все его магические атрибуты и вычеркнуто то, что на самом деле было определено. Так... как я могу получить эти поля? Вероятно, у них есть функция для извлечения их для своих внутренних целей?
10 ответов
для Django версии 1.8 и более поздних версий:
на get_all_field_names()
метод устаревший начиная с Django 1.8 и будет удален в 1.10.
страница документации, связанная выше, обеспечивает полностью обратно совместимую реализацию get_all_field_names()
, но для большинства целей [f.name for f in MyModel._meta.get_fields()]
должно работать нормально.
для версий Django до 1.8:
model._meta.get_all_field_names()
это должно сделать трюк.
для этого требуется фактическая модель пример. Если у вас есть подкласс django.db.models.Model
, тогда вы должны позвонить myproject.myapp.models.MyModel._meta.get_all_field_names()
на get_all_related_fields()
метод, упомянутый здесь, был осуждается в 1.8. Отныне это get_fields()
.
>> from django.contrib.auth.models import User
>> User._meta.get_fields()
Я считаю, что добавление этого в модели 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
Это делает трюк. Я тестирую его только в 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
.
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
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)
)))
чтобы добавить, я использую self object, это сработало для меня:
[f.name for f in self.model._meta.get_fields()]
непонятно, есть ли у вас экземпляр класса или сам класс и пытаются извлечь поля, но в любом случае, рассмотрим следующий код
использованием экземпляра
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'
по крайней мере с 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']
почему бы просто не использовать:
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'),)