Django: получить список полей модели?
я определил a User класс, который (в конечном счете) наследует от models.Model. Я хочу получить список всех полей, определенных для этой модели. Например, phone_number = CharField(max_length=20). В принципе, я хочу получить все, что наследует от Field класса.
Я думал, что смогу получить их, воспользовавшись inspect.getmembers(model), но он возвращает список не содержит ни одного из этих полей. Похоже, что Django уже завладел классом и добавил все свои магические атрибуты и убрали то, что на самом деле было определено. Так... как я могу получить эти поля? Вероятно, у них есть функция для их извлечения для своих собственных внутренних целей?
10 ответов:
для версий Django 1.8 и более поздних:
The
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()
The
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'
по крайней мере с 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']
почему бы просто не использовать:
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'),)
Comments