J'ai une classe modèle dont je veux que deux champs soient des champs de choix, donc pour remplir ces choix, j'utilise une énumération comme indiqué ci-dessous
#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)
Cependant, lorsque j'essaie d'accéder à ce modèle via l'administrateur, j'obtiens l'erreur suivante:
Django Version: 1.11
Exception Type: ValueError
Exception Value:
too many values to unpack (expected 2)
J'ai suivi deux articles qui décrivaient comment utiliser les énumérations:
Pour Django 2.x et inférieur:
Vous définissez un Enum
en définissant les différentes options comme indiqué ici :
class TransactionStatus(Enum):
INITIATED = "INITIATED"
PENDING = "PENDING"
COMPLETED = "COMPLETED"
FAILED = "FAILED"
ERROR = "ERROR"
Notez qu'il n'y a pas de virgule! Cela vous permet plus tard dans votre code de faire référence à TransactionStatus.ERROR
ou TransactionStatus.PENDING
.
Le reste de votre code est correct. Vous obtenez le choices
en créant des tuples de option.name
, option.value
.
MISE À JOUR: Pour Django 3.x et supérieur , utilisez les types intégrés TextChoices
, IntegerChoices
et Choices
comme décrit ici . De cette façon, vous n'avez pas à construire vous-même le choices
Tuple.
Exemple:
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,
)
Ceux-ci fonctionnent de manière similaire à enum de la bibliothèque standard de Python, mais avec quelques modifications:
label
. Le label
peut être un chaîne traduisible paresseuse. Ainsi, dans la plupart des cas, la valeur du membre sera un (value, label)
deux-Tuple. Si aucun Tuple n'est fourni, ou si le dernier élément n'est pas une chaîne (paresseuse), l'étiquette est - généré automatiquement à partir du nom du membre..label
Est ajoutée aux valeurs, pour renvoyer le nom lisible par l'homme. Un certain nombre de propriétés personnalisées sont ajoutées aux classes d'énumération - .choices
, .labels
, .values
Et .names
- pour faciliter l'accès aux listes de ces parties distinctes de l'énumération. Utilisez .choices
Comme valeur appropriée pour passer aux choix dans une définition de champ.enum.unique()
est appliquée pour garantir que les valeurs ne peuvent pas être définies plusieurs fois. Il est peu probable que cela soit prévu dans les choix d'un champ.Pour plus d'informations, consultez la documentation
Le problème dans votre code est que INITIATED = "INITIATED",
une virgule après l'option INITIATED
et d'autres options. lorsque nous ajoutons une virgule après une chaîne, elle devient un tuple. Voir un exemple ci-dessous
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())
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)