[英]How to map Django TextChoices text to a choice?
Suppose I have this code, inspired from the Django docs about enumeration types:假设我有这段代码,灵感来自Django关于枚举类型的文档:
class YearInSchool(models.TextChoices):
FRESHMAN = 'FR', 'Freshman'
SOPHOMORE = 'SO', 'Sophomore'
JUNIOR = 'JR', 'Junior'
SENIOR = 'SR', 'Senior'
GRADUATE = 'GR', 'Graduate'
Now suppose I have the string "Sophomore".现在假设我有字符串“Sophomore”。 How do I get from that to
YearInSchool.SOPHOMORE
?我如何从那里到
YearInSchool.SOPHOMORE
?
The only thing I can think of is a loop:我唯一能想到的就是循环:
the_str = "Sophomore"
val = None
for val1, label in YearInSchool.choices:
if label == the_str:
val = YearInSchool(val1)
break
assert YearInSchool.SOPHOMORE == val
That seems awkward.这似乎很尴尬。 Is there a better way?
有没有更好的办法?
EDIT : Thanks for the answers folks.编辑:感谢大家的回答。 I'll try them out, Just to provide more context, I am loading data from text files into a database.
我会尝试一下,为了提供更多上下文,我将文本文件中的数据加载到数据库中。 so the "Sophomore" is in a text file I've been provided that wasn't created by me, So, I'm stretching the use case for TextChoices.
所以“二年级”在我提供的一个文本文件中,它不是我创建的,所以,我正在扩展 TextChoices 的用例。 but it seemed a reasonable way to tie text file input to a DB field.
但这似乎是将文本文件输入绑定到数据库字段的合理方法。
I'm affraid Django doesn't implement a similar method to get_FOO_display
(described here in the doc) to achieve what you want, but I think models.TextChoices
is not intended to be used this way.我很害怕 Django 没有实现与
get_FOO_display
类似的方法(在文档中描述) 来实现你想要的,但我认为models.TextChoices
不打算以这种方式使用。
For instance, a POST request should directly contain YearInSchool.FRESHMAN.value
instead of YearInSchool.FRESHMAN.label
(at least, this is the default behavior in django.forms
), so that should not be your concern.例如,POST 请求应直接包含
YearInSchool.FRESHMAN.value
而不是YearInSchool.FRESHMAN.label
(至少,这是django.forms
中的默认行为),因此您不必担心。
This being said, here is a one-liner solution which would raise a ValueError
if the_str
is not found:话虽这么说,这是一个单行解决方案,如果
the_str
,它会引发ValueError
:
val = YearInSchool.values[YearInSchool.labels.index(the_str)]
And another similar solution, twice as fast:另一个类似的解决方案,速度是原来的两倍:
try:
val = next(filter(lambda x: x[1] == the_str, YearInSchool.choices))[0]
except StopIteration as err:
raise ValueError(f"{the_str} not found in {YearInSchool.labels}") from err
You can use getattr
:您可以使用
getattr
:
the_str = 'Sophomore'
try:
val = getattr(YearInSchool, the_str.upper())
except AttributeError:
raise AttributeError(f'{the_str.upper()} not found in {YearInSchool.names}')
assert val == YearInSchool.SOPHOMORE
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.