我有一个模型类,我希望将两个字段作为选择字段,因此为了填充这些选择,我使用了下面列出的枚举
#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)
我关注了以下两篇使用枚举的文章:
https://hackernoon.com/using-enum-as-model-field-choice-in-django-92d8b97aaa63
https://blog.richard.do/2014/02/18/how-to-use-enums-for-django-field-choices/
答案 0 :(得分:10)
示例:
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,
)
这些工作类似于Python标准库中的enum,但进行了一些修改:
label
。 label
可以是懒惰的可翻译字符串。因此,在大多数情况下,成员值将为(value, label)
两元组。如果未提供元组,或者最后一项不是(惰性)字符串,则标签为成员名称中的automatically generated。.label
属性,以返回人类可读的名称。
大量自定义属性已添加到枚举类– .choices
,.labels
,.values
和.names
–使访问访问列表中这些单独部分的列表更加容易列举。使用.choices
作为合适的值,以传递到字段定义中的选择。enum.unique()
以确保不能多次定义值。在字段选择中这不太可能达到预期。有关更多信息,请check the documentation
答案 1 :(得分:2)
如果您收到此错误:
<块引用>'choices' 必须是一个包含(实际值,可读名称)元组的可迭代对象
并且正在使用 Django3,那么您可能遇到了与我相同的问题:“枚举”必须嵌入到您尝试使用它们的模型中,并且不能在模型之外声明。例如,这将不起作用:
class YearInSchool(models.TextChoices):
FRESHMAN = 'FR', _('Freshman')
SOPHOMORE = 'SO', _('Sophomore')
JUNIOR = 'JR', _('Junior')
SENIOR = 'SR', _('Senior')
GRADUATE = 'GR', _('Graduate')
class Student(models.Model):
year_in_school = models.CharField(
max_length=2,
choices=YearInSchool.choices,
default=YearInSchool.FRESHMAN,
)
文档中的这个示例将:
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,
)
答案 2 :(得分:0)
您的代码中的问题是response($.map(data.data, function (item, i) {
//alert(item.value);
return {
id: item.id,
label: item.label,
value: item.value
}
})
);
选项和其他选项之后的INITIATED = "INITIATED",
是逗号。当我们在任何字符串后添加逗号时,它将成为一个元组。参见下面的示例
INITIATED
s = 'my str'
print(type(s))
# output: str
s = 'my str',
print(type(s))
# output: tuple
class Transaction(models.Model):
trasaction_status = models.CharField(max_length=255, choices=TransactionStatus.choices())
transaction_type = models.CharField(max_length=255, choices=TransactionType.choices())
答案 3 :(得分:0)
您可以按照here所述设置各种选项来定义Enum
:
class TransactionStatus(Enum):
INITIATED = "INITIATED"
PENDING = "PENDING"
COMPLETED = "COMPLETED"
FAILED = "FAILED"
ERROR = "ERROR"
注意没有逗号!这样一来,您便可以在以后的代码中引用TransactionStatus.ERROR
或TransactionStatus.PENDING
。
其余的代码是正确的。您可以通过创建choices
,option.name
的元组来获得option.value
。
答案 4 :(得分:0)
顺便说一句,Djanog还支持Python 3的auto()作为Enum值。您可以使用以下帮助程序类来简化生活。
from django.db.models.enums import TextChoices
class AutoEnumChoices(TextChoices):
def _generate_next_value_(name, start, count, last_values): # @NoSelf
return name.lower()
@property
def choices(cls): # @NoSelf
empty = [(None, cls.__empty__)] if hasattr(cls, '__empty__') else []
return empty + [(member.value, member.label) for member in cls]
然后在您的选择定义中使用它:
class TransferBasicStatus(AutoEnumChoices):
NONE = auto()
WAITING = auto()
PENDING = auto()
PROGRESS = auto()
SUCCESS = auto()
DECLINED = auto()
ENDED = 'ended', _('Ended - The transfer has ended with mixed states')
答案 5 :(得分:0)
您可以尝试根据 examples from docs. 执行类似操作:
from enum import Enum
class BaseEnum(Enum):
def __new__(cls, *args):
obj = object.__new__(cls)
obj._value_ = args[0]
obj.display_name = args[1]
return obj
@classmethod
def model_choices(cls):
return [(cls.__members__[member].value, cls.__members__[member].display_name)
for member in cls.__members__.keys()]
这将导致:
>>> class TransactionType(BaseEnum):
... IN = ('in', 'In')
... OUT = ('out', 'Out')
...
>>> TransactionType.IN.value
'in'
>>> TransactionType.IN.display_name
'In'
>>> TransactionType.model_choices()
[('in', 'In'), ('out', 'Out')]
可以用作字段选择的参数。
答案 6 :(得分:0)
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,
)
对于 Django 3.0 以上,你可以使用上面的例子。
对于整数选择,您可以使用以下代码。
class Suit(models.IntegerChoices):
DIAMOND = 1
SPADE = 2
HEART = 3
CLUB = 4
suit = models.IntegerField(choices=Suit.choices)
答案 7 :(得分:-1)
根据您对https://hackernoon.com/using-enum-as-model-field-choice-in-django-92d8b97aaa63的引用。选择应该是元组列表,而您将返回元组的元组。 我的更多信息与i.name不同。试试:
#enums.py
class TransactionType(Enum):
IN = "IN",
OUT = "OUT"
@classmethod
def choices(cls):
return [(i, i.value) for i in cls]