Magazine Internet

Django extended choices

Publié le 16 août 2011 par Samuel Martin

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

  1. Vous souhaitez obtenir une liste de tuples, utile pour remplir vos DjangoForm : STATES.CHOICES
  2. Vous souhaitez obtenir la valeur d'une constante : STATES.ONLINE --> 1
  3. Vous souhaitez obtenir le "label" STATES.CHOICES_DICT[1] --> 'Online' ou 'En ligne' selon la langue
  4. Vous souhaitez obtenir le nom de la constante (voir le patch qui suit) STATES.CHOICES_VARNAMEDICT[1] --> 'ONLINE'
  5. 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)


Retour à La Une de Logo Paperblog

A propos de l’auteur


Samuel Martin 21 partages Voir son profil
Voir son blog

l'auteur n'a pas encore renseigné son compte l'auteur n'a pas encore renseigné son compte

Dossier Paperblog

Magazine