Par*_*ras 8 python django enums django-models python-3.x
I have a model class of which I want two fields to be a choice fields, so to populate those choices I am using an enum as listed below
#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)
Run Code Online (Sandbox Code Playgroud)
However, when I am trying to access this model through admin I am getting the following error :
Django Version: 1.11
Exception Type: ValueError
Exception Value:
too many values to unpack (expected 2)
Run Code Online (Sandbox Code Playgroud)
I followed two articles that described how to use enums:
您的代码中的问题是选项和其他选项INITIATED = "INITIATED",
后的逗号INITIATED
。当我们在任何字符串后添加逗号时,它将成为一个元组。请参阅下面的示例
s = 'my str'
print(type(s))
# output: str
s = 'my str',
print(type(s))
# output: tuple
Run Code Online (Sandbox Code Playgroud)
class Transaction(models.Model):
trasaction_status = models.CharField(max_length=255, choices=TransactionStatus.choices())
transaction_type = models.CharField(max_length=255, choices=TransactionType.choices())
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
例:
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,
)
Run Code Online (Sandbox Code Playgroud)
这些工作类似于Python标准库中的枚举,但有一些修改:
label
。该label
可以是一个懒惰的翻译字符串。因此,在大多数情况下,成员值将是一个(value, label)
二元组。如果未提供元组,或者最后一项不是(惰性)字符串,那么将从成员名自动生成标签。.label
在值上添加一个属性,以返回人类可读的名称。许多自定义属性添加到枚举类- ,,.choices
和-更容易为枚举的这些独立部分的访问列表。使用作为一个合适的值传递给选择在字段定义。.labels
.values
.names
.choices
enum.unique()
强制使用,以确保不能多次定义值。在字段选择中这不太可能被期望。有关更多信息,请查看文档
您可以Enum
通过设置此处所述的各种选项来定义一个:
class TransactionStatus(Enum):
INITIATED = "INITIATED"
PENDING = "PENDING"
COMPLETED = "COMPLETED"
FAILED = "FAILED"
ERROR = "ERROR"
Run Code Online (Sandbox Code Playgroud)
注意没有逗号!这使您稍后可以在代码中引用TransactionStatus.ERROR
或TransactionStatus.PENDING
。
您的其余代码是正确的。你得到choices
通过创建的元组option.name
,option.value
。
我的项目的一个例子:
import enum
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.utils.translation import gettext_lazy as _
class NotificationTemplate(models.Model):
class Meta:
verbose_name = _('notification template')
verbose_name_plural = _('notification templates')
@enum.unique
class Name(str, enum.Enum):
ONBOARDING = 'onboarding'
TG_ERROR = 'tg_error'
FB_ERROR = 'fb_error'
@classmethod
def choices(cls):
return [(item.value, item.name) for item in cls]
@enum.unique
class Type(int, enum.Enum):
PUSH = 1
EMAIL = 2
TELEGRAM = 3
VK = 4
OTHER = 5
@classmethod
def choices(cls):
return [(item.value, item.name) for item in cls]
name = models.CharField(_('notification name'), max_length=64, unique=True, choices=Name.choices(), default=Name.ONBOARDING)
template_type = ArrayField(models.PositiveSmallIntegerField(_('type'), choices=Type.choices()))
max_count = models.PositiveSmallIntegerField(default=1)
def __str__(self):
return self.Name(self.name).name
Run Code Online (Sandbox Code Playgroud)