Когда у вас есть поле модели с опцией выбора, у вас, как правило, есть некоторые магические значения, связанные с понятными человеку именами. Есть ли в Django удобный способ установить эти поля по удобочитаемому имени вместо значения?
Рассмотрим эту модель:
class Thing(models.Model):
PRIORITIES = (
(0, 'Low'),
(1, 'Normal'),
(2, 'High'),
)
priority = models.IntegerField(default=0, choices=PRIORITIES)
В какой-то момент у нас есть экземпляр Thing, и мы хотим установить его приоритет. Очевидно, вы могли бы сделать,
thing.priority = 1
Но это заставляет вас запоминать сопоставление ПРИОРИТЕТОВ имени значения. Это не работает:
thing.priority = 'Normal' # Throws ValueError on .save()
В настоящее время у меня есть этот глупый обходной путь:
thing.priority = dict((key,value) for (value,key) in Thing.PRIORITIES)['Normal']
но это неуклюже. Учитывая, насколько распространен этот сценарий, мне было интересно, есть ли у кого-нибудь лучшее решение. Есть ли какой-нибудь полевой метод для установки полей по имени выбора, который я полностью упустил?
источник
Я бы, наверное, установил обратный поиск раз и навсегда, но если бы я этого не делал, я бы просто использовал:
что кажется проще, чем создать диктант на лету, чтобы просто выбросить его снова ;-).
источник
Вот тип поля, который я написал несколько минут назад, и я думаю, он делает то, что вы хотите. Для его конструктора требуется аргумент choices, который может быть либо кортежем из двух кортежей в том же формате, что и параметр choices для IntegerField, либо вместо этого простым списком имен (например, ChoiceField (('Low', 'Normal', 'High'), по умолчанию = 'Low')). Класс заботится о преобразовании строки в int за вас, вы никогда не увидите int.
источник
Я ценю постоянный способ определения, но считаю, что тип Enum лучше всего подходит для этой задачи. Они могут одновременно представлять целое число и строку для элемента, сохраняя при этом ваш код более читабельным.
Перечисления были введены в Python в версии 3.4. Если вы используете какой - либо ниже (например, v2.x) , вы все равно можете иметь его, установив портированном пакет :
pip install enum34
.Это почти все. Вы можете наследовать,
ChoiceEnum
чтобы создавать свои собственные определения и использовать их в определении модели, например:Запросы - это вишенка на торте, как вы могли догадаться:
Их также легко представить в виде строки:
источник
ChoiceEnum
вы можете использовать.value
и в.name
качестве @kirpit описывает и заменить использованиеchoices()
сtuple([(x.value, x.name) for x in cls])
--either в функции (DRY) или непосредственно в конструкторе поля.Используйте это так:
источник
Начиная с Django 3.0, вы можете использовать:
источник
Просто замените свои числа желаемыми для человека значениями. В качестве таких:
Это делает его удобочитаемым, однако вам придется определять свой собственный порядок.
источник
Мой ответ очень запоздалый и может показаться очевидным нынешним экспертам по Django, но тем, кто сюда попадает, я недавно обнаружил очень элегантное решение, предложенное django-model-utils: https://django-model-utils.readthedocs.io/ ru / latest / utilities.html # choices
Этот пакет позволяет вам определять варианты выбора с помощью трех кортежей, где:
Итак, вот что вы можете сделать:
Сюда:
Наслаждаться :)
источник
priority = models.IntegerField(default=PRIORITIES.Low, choices=PRIORITIES)
(разумеется, для этого необходимо, чтобы присвоение приоритета находилось внутри класса Thing). Также рассмотрите возможность использования строчных слов / символов для идентификатора python, поскольку вы ссылаетесь не на класс, а на параметр (тогда ваш выбор будет выглядеть следующим образом:(0, 'low', 'Low'),
и т. Д.).Первоначально я использовал модифицированную версию ответа @Allan:
Упрощенный
django-enumfields
пакет, который я сейчас использую:источник
Опция выбора модели принимает последовательность, состоящую из итераций ровно двух элементов (например, [(A, B), (A, B) ...]) для использования в качестве вариантов выбора для этого поля.
Кроме того, Django предоставляет типы перечисления , которые можно подклассифицировать для краткого определения вариантов:
Django поддерживает добавление дополнительного строкового значения в конец этого кортежа для использования в качестве удобочитаемого имени или метки. Метка может быть ленивой переводимой строкой.
Примечание: Вы можете использовать это , используя
ThingPriority.HIGH
,ThingPriority.['HIGH']
илиThingPriority(0)
для доступа или подстановок членов перечислений.источник