Django extended choices permet de gérer avec simplicité et efficacité les constantes au sein d'une application Django. Cet article fait suite à la publication de J-Mad.
Installation
git clone https://github.com/twidi/django-extended-choices/tree/master
Comment ça marche ?
Avant l'utilisation du plugin
STATE_ONLINE = 1 STATE_DRAFT = 2 STATE_OFFLINE = 3 STATE_CHOICES = ( (STATE_ONLINE, 'Online'), (STATE_DRAFT, 'Draft'), (STATE_OFFLINE, 'Offline'), ) STATE_DICT = dict(STATE_CHOICES) class ContentModel(models.Model): title = models.CharField(max_length=255) content = models.TextField() state = models.PositiveSmallIntegerField(choices=STATE_CHOICES, default=STATE_DRAFT) related_to = models.ManyToManyField('self', through="ContentToContent", symmetrical=False, blank=True, null=True) def __unicode__(self): return u'Content "%s" (state=%s)' % (self.title, STATE_DICT[self.state]) def get_related_content(self): return self.related_to.select_related().filter(state=STATE_ONLINE)
Après l'utilisation du plugin
from extended_choices import Choices from django.utils.translation import ugettext_lazy as _ STATES = Choices( ('ONLINE', 1, _(u'Online')), ('DRAFT', 2, _(u'Draft')), ('OFFLINE', 3, _(u'Offline')), ) class ContentModel(models.Model): title = models.CharField(max_length=255) content = models.TextField() state = models.PositiveSmallIntegerField(choices=STATES.CHOICES, default=STATES.DRAFT) related_to = models.ManyToManyField('self', through="ContentToContent", symmetrical=False, blank=True, null=True) def __unicode__(self): return u'Content "%s" (state=%s)' % (self.title, STATES.CHOICES_DICT[self.state]) def get_related_content(self): return self.related_to.select_related().filter(state=STATES.ONLINE)
Plus clair non ?
Récapitulatif
- Vous souhaitez obtenir une liste de tuples, utile pour remplir vos DjangoForm :
STATES.CHOICES
- Vous souhaitez obtenir la valeur d'une constante :
STATES.ONLINE --> 1
- Vous souhaitez obtenir le "label"
STATES.CHOICES_DICT[1] --> 'Online' ou 'En ligne' selon la langue
- Vous souhaitez obtenir le nom de la constante (voir le patch qui suit)
STATES.CHOICES_VARNAMEDICT[1] --> 'ONLINE'
- Vous souhaitez utiliser une syntaxe "tableau" pour éviter que Aptana vous engueule (voir également patch qui suit - Merci Mickaël Hoareau)
STATES['ONLINE']
Version patchée
# -*- coding: utf-8 -*- class Choices(dict): def __init__(self, *choices, **kwargs): name = kwargs.get('name', 'CHOICES') self.add_choices(name, *choices) def add_choices(self, name, *choices): CHOICES = [] CHOICES_DICT = {} CHOICES_RDICT = {} CHOICES_VARNAMEDICT = {} for choice in choices: const, value, string = choice if not hasattr(self, const): setattr(self, const, value) else: value = getattr(self, const) CHOICES.append((value, string)) CHOICES_DICT[value] = string CHOICES_RDICT[string] = value CHOICES_VARNAMEDICT[value] = const setattr(self, name, tuple(CHOICES)) setattr(self, '%s_DICT' % name, CHOICES_DICT) setattr(self, '%s_RDICT' % name, CHOICES_RDICT) setattr(self, '%s_RDICT' % name, CHOICES_RDICT) setattr(self, '%s_VARNAMEDICT' % name, CHOICES_VARNAMEDICT) def __getitem__(self, key): if not hasattr(self, key): raise KeyError("Key Error : '" + str(key) + "' not found") return getattr(self, key)