简体   繁体   English

如何将map Django TextChoices 文本进行选择?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM