Code


Version 1 (modified by akaihola, 8 years ago) (diff)

--

In a Django-users thread, Ned Batchelder presented a neat trick to provide constants for the choices= functionality of Django models. His solution auto-generates verbose choice names for drop-down menus in the admin, and also allows overriding them. The property names can be used when the constants are needed in the code, so there's no need to remember arbitrary integers or strings. Here's the code:

class K:
    def __init__(self, label=None, **kwargs):
        assert(len(kwargs) == 1)
        for k, v in kwargs.items():
            self.id = k
            self.v = v
        self.label = label or self.id

class Constants:
    def __init__(self, *args):
        self.klist = args
        for k in self.klist:
            setattr(self, k.id, k.v)

    def choices(self):
        return [(k.v, k.label) for k in self.klist]

Example definition of choices:

kBranchKind = Constants(
    K(main=1, label='Main branch'),
    K(dead=2, label='An ex-branch'),
    K(aux=3)    # I don't know how to spell 'Auxilliary' anyway!
)

In your code, you can use kBranchKind.dead, and in your model, you can use:

class Branch(meta.Model):
    trunk = meta.ForeignKey(Trunk)
    kind = meta.IntegerField(choices=kBranchKind.choices())

It keeps the list of choices in one place, gives you run-time errors if you mistype the constant name (string literals would not), and it works just as well with strings for the values.