Django: получить список полей модели?



я определил a User класс, который (в конечном счете) наследует от models.Model. Я хочу получить список всех полей, определенных для этой модели. Например, phone_number = CharField(max_length=20). В принципе, я хочу получить все, что наследует от Field класса.



Я думал, что смогу получить их, воспользовавшись inspect.getmembers(model), но он возвращает список не содержит ни одного из этих полей. Похоже, что Django уже завладел классом и добавил все свои магические атрибуты и убрали то, что на самом деле было определено. Так... как я могу получить эти поля? Вероятно, у них есть функция для их извлечения для своих собственных внутренних целей?

692   10  

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

    Ничего не найдено.