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)