| 1 | In a [http://groups.google.com/group/django-users/browse_frm/thread/c054672bfeb8979d/9e2cda1f270f0dd4 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: |
| 2 | |
| 3 | {{{ |
| 4 | class K: |
| 5 | def __init__(self, label=None, **kwargs): |
| 6 | assert(len(kwargs) == 1) |
| 7 | for k, v in kwargs.items(): |
| 8 | self.id = k |
| 9 | self.v = v |
| 10 | self.label = label or self.id |
| 11 | |
| 12 | class Constants: |
| 13 | def __init__(self, *args): |
| 14 | self.klist = args |
| 15 | for k in self.klist: |
| 16 | setattr(self, k.id, k.v) |
| 17 | |
| 18 | def choices(self): |
| 19 | return [(k.v, k.label) for k in self.klist] |
| 20 | }}} |
| 21 | |
| 22 | Example definition of choices: |
| 23 | |
| 24 | {{{ |
| 25 | kBranchKind = Constants( |
| 26 | K(main=1, label='Main branch'), |
| 27 | K(dead=2, label='An ex-branch'), |
| 28 | K(aux=3) # I don't know how to spell 'Auxilliary' anyway! |
| 29 | ) |
| 30 | }}} |
| 31 | |
| 32 | In your code, you can use {{{kBranchKind.dead}}}, and in your model, you |
| 33 | can use: |
| 34 | |
| 35 | {{{ |
| 36 | class Branch(meta.Model): |
| 37 | trunk = meta.ForeignKey(Trunk) |
| 38 | kind = meta.IntegerField(choices=kBranchKind.choices()) |
| 39 | }}} |
| 40 | |
| 41 | It keeps the list of choices in one place, gives you run-time errors if |
| 42 | you mistype the constant name (string literals would not), and it works |
| 43 | just as well with strings for the values. |