python - 如何在 Django 模型中使用枚举作为选择字段

标签 python django python-3.x django-models enums

我有一个模型类,我希望其中的两个字段成为一个选择字段,因此为了填充这些选择,我正在使用下面列出的枚举

#models.py
class Transaction(models.Model):
    trasaction_status = models.CharField(max_length=255, choices=TransactionStatus.choices())
    transaction_type = models.CharField(max_length=255, choices=TransactionType.choices())

#enums.py
class TransactionType(Enum):

    IN = "IN",
    OUT = "OUT"

    @classmethod
    def choices(cls):
        print(tuple((i.name, i.value) for i in cls))
        return tuple((i.name, i.value) for i in cls)

class TransactionStatus(Enum):

    INITIATED = "INITIATED",
    PENDING = "PENDING",
    COMPLETED = "COMPLETED",
    FAILED = "FAILED"
    ERROR = "ERROR"

    @classmethod
    def choices(cls):
        print(tuple((i.name, i.value) for i in cls))
        return tuple((i.name, i.value) for i in cls)

但是,当我尝试通过管理员访问此模型时,出现以下错误:

Django Version: 1.11
Exception Type: ValueError
Exception Value:    
too many values to unpack (expected 2)

我关注了两篇描述如何使用枚举的文章:

最佳答案

Django 3.0 内置了对枚举的支持

例子:

from django.utils.translation import gettext_lazy as _

class Student(models.Model):

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

    year_in_school = models.CharField(
        max_length=2,
        choices=YearInSchool.choices,
        default=YearInSchool.FRESHMAN,
    )

These work similar to enum from Python’s standard library, but with some modifications:

  • Enum member values are a tuple of arguments to use when constructing the concrete data type. Django supports adding an extra string value to the end of this tuple to be used as the human-readable name, or label. The label can be a lazy translatable string. Thus, in most cases, the member value will be a (value, label) two-tuple. If a tuple is not provided, or the last item is not a (lazy) string, the label is automatically generated from the member name.
  • A .label property is added on values, to return the human-readable name. A number of custom properties are added to the enumeration classes – .choices, .labels, .values, and .names – to make it easier to access lists of those separate parts of the enumeration. Use .choices as a suitable value to pass to choices in a field definition.
  • The use of enum.unique() is enforced to ensure that values cannot be defined multiple times. This is unlikely to be expected in choices for a field.

欲了解更多信息,check the documentation

注意事项:

正如@Danielle Madeley 指出的那样,如果您尝试直接访问 year_in_school 属性,Django 仍然返回原始字符串而不是 Enum 对象:

>>> student.year_in_school
'FR'

我通常做的是创建一个返回 Enum 对象的辅助方法:

class Student(models.Model):
    ...

    def get_year_in_school(self) -> YearInSchool:
        # Get value from choices enum
        return self.YearInSchool[self.year_in_school]

关于python - 如何在 Django 模型中使用枚举作为选择字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54802616/

相关文章:

python - 一元操作数类型错误 + : 'str'

python - 获取 pdb 中的最后一个异常

python - 如何 : Redis in production server

Django 自定义管理操作 : how to deselect on completion?

python - 如何标准化 pandas DataFrame 中行之间的字符串?

Python azure-identity ClientSecretCredential

提交表单时,javascript blockUI 在 firefox 中不起作用

python-3.x - Pandas groupby 并附加原始值。计算每行的平均值

python-3.x - 如何使用 Pandas 从字符串中提取算术运算

python - Pandas reshape 从 colname 中提取多个值