Django TextChoices 行为

问题描述 投票:0回答:4
class MyTypes(TextChoices):
    MINE_AAA = '1', 'a',
    MINE_BBB = '2', 'b',
    MINE_CCC = '3', 'c',
    MINE_DDD = '4', 'd',
    MINE_EEE = '5', 'e'

    my_type = models.CharField(max_length=1, choices=MyTypes.choices)

我一直在努力在我的模型中使用选项。在上面的例子中,如果我创建一个实例“my_obj”并将“my_obj.my_type”设置为“MyTypes.MINE_BBB”,那么如果我查看“my_obj”,它的类型是MyTypes。但是,如果我稍后查询“my_obj”并查看“my_obj.my_type”,它的类型现在是字符串。

因此,当我最初创建对象并序列化它时,序列化程序需要处理 MyTypes,但是如果我在查询后序列化该值,序列化程序需要处理字符串。

使用 TextChoices 字段时,我真正期望的是存储在数据库中的值将是单个字符,但是当我在代码中引用它时,我会看到我的 MyTypes。

当我们引用模型时,我们不应该取回 TextChoices 实例吗?如果没有,最简单的获取方法是什么?看起来,如果我在迭代 MyTypes.choices 来获取它之后,它确实没有提供太多价值。

这是文档的样子。

class YearInSchool(models.TextChoices):
        FRESHMAN = 'FR', _('Freshman')
        SOPHOMORE = 'SO', _('Sophomore')
        JUNIOR = 'JR', _('Junior')
        SENIOR = 'SR', _('Senior')
        GRADUATE = 'GR', _('Graduate')
django
4个回答
5
投票

您可以像这样获取

MyTypes
实例:

MyTypes('1') == MyTypes.MINE_AAA

因此,在您的代码中,每当您想要

my_obj
的类型时,作为 MyTypes 实例,您都可以执行
MyType(my_obj.my_type)

我建议为其编写一个方法:

class MyModel(models.model):
    class MyType(TextChoices):
        ...

    my_type = models.CharField(max_length=1, choices=MyTypes.choices)

    def get_type(self):
        return MyModel.MyType(self.my_type)

0
投票

选择字段需要是元组列表

class MyTypes(TextChoices):
    MINE_AAA = ('1', 'a',)
    MINE_BBB = ('2', 'b',)
    MINE_CCC = ('3', 'c',)
    MINE_DDD = ('4', 'd',)
    MINE_EEE = ('5', 'e')

    MY_CHOICES = [
        MINE_AAA,
        MINE_BBB,
        MINE_CCC,
        MINE_DDD,
        MINE_EEE
    ]

    my_type = models.CharField(max_length=1, choices=MY_CHOICES)

这是文档的样子。

class YearInSchool(models.TextChoices):
        FRESHMAN = 'FR', _('Freshman')
        SOPHOMORE = 'SO', _('Sophomore')
        JUNIOR = 'JR', _('Junior')
        SENIOR = 'SR', _('Senior')
        GRADUATE = 'GR', _('Graduate')

0
投票

用于性别选择的TextChoice,首先你必须导入

从 django.utils.translation 导入 gettext_lazy as _

class Gender(models.TextChoices):
    MALE = "male", _("Male")
    FEMALE = "female", _("Female")
    OTHER = "other", _("Other")

0
投票

由于您从

MyTypes
继承了
TextChoices
,因此字段
my_type
可能会出现损坏的行为。 在文档中创建了本地类

class MyModel(models.Model):
    class MyTypes(models.TextChoices):
        MINE_AAA = '1', 'a',
        MINE_BBB = '2', 'b',
        MINE_CCC = '3', 'c',
        MINE_DDD = '4', 'd',
        MINE_EEE = '5', 'e'

    my_type = models.CharField(max_length=1, choices=MyTypes.choices)

TextChoices
是 python
Enum
类型的扩展,其行为与您可能习惯的有点不同。 查询
my_type
时,您将得到一个字符串,因为它是
CharField
,这就是它在数据库中的存储方式。字符串值始终是
MyTypes
类中的选择之一,例如:

>>> MyModel.objects.create(my_type=MyModel.MyTypes.MINE_AAA)
<MyModel: MyModel object (1)>
>>> a = MyModel.objects.get(my_type=MyModel.MyTypes.MINE_AAA)
>>> a.my_type == MyModel.MyTypes.MINE_AAA
True
>>> type(a.my_type)
str
>>> type(MyModel.MyTypes.MINE_AAA)
<enum 'MyTypes'>
>>> type(MyModel.MyTypes.MINE_AAA.value)
str

我建议使用

TextChoices
来简洁、方便,最重要的是为了整个代码库的一致性。您应该始终远离静态检查选择字段。 如果使用
TextChoice
被证明太麻烦,您可以使用更传统的方式来声明保存选择的变量和
CHOICES
元组(如果您打算改变它,则为列表) 在这个例子中使用
CHOICES
元组看起来像这样

class MyModel(models.Model):
    MINE_AAA = "1"
    MINE_BBB = "2"
    MINE_CCC = "3"
    MINE_DDD = "4"
    MINE_EEE = "5"

    CHOIES = (
        (MINE_AAA, "a"),
        (MINE_BBB, "b"),
        (MINE_CCC, "c"),
        (MINE_DDD, "d"),
        (MINE_EEE, "e"),
    )
    
    my_type = models.CharField(max_length = 1, choices=CHOICES)

您可以通过执行与之前几乎相同的操作来检查值,唯一的区别是实际变量本身也将是

str

>>> a = MyModel.objects.get(my_type=MyModel.MyTypes.MINE_AAA)
>>> a.my_type == MyModel.MINE_AAA
True
>>> type(MyModel.MINE_AAA)
str
© www.soinside.com 2019 - 2024. All rights reserved.