Отримати доступ до полів моделі Django, використовуючи рядок замість синтаксису крапок?


77

У Django я можу зробити це:

test = Test.objects.get(id=1)
test.name

Я хочу мати можливість отримати доступ до властивостей за допомогою динамічно генерованих рядків, наприклад:

test['name']

або будь-який інший синтаксис із використанням рядка. я намагався

test._meta.get_field_by_name('name')

але це повертає саме поле, а не значення.

Будь-які ідеї?

Відповіді:


112

Ви можете використовувати вбудовану getattr()функцію python :

getattr(test, 'name')

2
Хвилина занадто повільно! Не слід було витрачати час на тестування;)
Каспар

2
Ах, мені навіть не довелося користуватися функціональністю Django, і я дізнався щось нове про Python. Дякую за допомогу.
davidscolgan

Працює для ForeignKey?
Джанкарло Вентура,

Хтось знав би, як ми називаємо це в рамках внутрішнього методу класу для згаданої моделі .... self.getattr(SelfModelName, 'id')= ??
Майкл Дж. Робертс,

Трохи пізно, але ви можете просто використовувати getattr (self, 'id')
Brouwer

15

Якщо припустити, що ім'я є атрибутом тесту вашого екземпляра, воно getattr(test, 'name')має повернути відповідне значення. Або test.__dict__['name'].

Детальніше про це можна прочитати getattr()тут: http://effbot.org/zone/python-getattr.htm


12

Інші відповіді все ще стоять, але тепер ви можете зробити це за допомогою _meta.get_field від Django ().

test._meta.get_field('name')

Зверніть увагу, що API Model _meta розпочав свою офіційну підтримку та документацію з 1.8, але розповсюджувався та використовувався у попередніх версіях до офіційної документації.


2
Це все одно повертає саме поле, і ОП цікавило значення поля.
rob3c

6

У Python ви можете зазвичай отримувати доступ до значень в об'єкті, який має dict метод .

Скажімо, у вас є такий клас:

class Dog(object):
    def __init___(self, color):
        self.color = color

І тоді я створюю його на прикладі:

dog = Dog('brown')

Тож я бачу колір, виконуючи:

print dog.color

Я також бачу колір, виконуючи:

print dog.__dict__['color']

Я можу встановити колір:

print dog.__dict__['color'] = 'green'

print dog.color

>>>green

1
Це буде працювати, але загалом, ви хочете уникати використання підкреслених атрибутів / методів, якщо це можливо. Це сигнал про те, що вони нестабільні (відкриті для повного знищення або зміни по суті в будь-який час, без попередження) або не призначені бути частиною загальнодоступного інтерфейсу з якоїсь іншої причини. Іноді доводиться, але в цьому випадку getattrдоступний варіант є правильним вибором.
Кріс Пратт,

@ChrisPratt Існує різниця між одинарним підкресленням, подвійним підкресленням та подвійним підкресленням із кінцевим подвійним підкресленням. Хоча те, що ви сказали, застосовується (більш-менш) до перших двох, метод передбачає, що він є вбудованим, і не вказує на конфіденційність чи захист, і там, де ви зазвичай виконуєте перевантаження та ініціалізацію оператора. docs.python.org/reference/datamodel.html#specialnames siafoo.net/article/57 stackoverflow.com/questions/1301346 / ...
ashwoods

1
@ashwoods: правда, але навіть тоді їх використання, як правило, міститься в іншому класі, тому це свого роду внутрішній код, що використовує ситуацію внутрішнього коду. Зрештою, ти, як правило, не використовуєш таких методів у дикій природі лише в інших класах, які все ще виводять конкретну реалізацію з "загальнодоступного" інтерфейсу.
Chris Pratt

@ChrisPratt, на даний момент це все досить академічно, але якщо ви посилаєтесь на сторінку 84 Python у "Послідовному слові", друге видання, він описує цю поведінку. Він каже: "Немає різниці між атрибутами класу, створеними в тілі класу, поза тілом шляхом присвоєння атрибута або поза тілом, явно прив'язавши запис у C .__ dict__. Тим не менше, я погоджуюсь, що getattr, мабуть, є правильним рішення в цій обставині, але це не означає, що не можна застосовувати дикт, що знаходиться поза тілом класу, або будь-який інший метод подвійного підкреслення.
Джеймс Р,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.