Set Django IntegerField by choices=... name


When you have a model field with a choices option you tend to have some magic values associated with human readable names. Is there in Django a convenient way to set these fields by the human readable name instead of the value?

Consider this model:

class Thing(models.Model):
    (0, 'Low'),
    (1, 'Normal'),
    (2, 'High'),

  priority = models.IntegerField(default=0, choices=PRIORITIES)

At some point we have a Thing instance and we want to set its priority. Obviously you could do,

thing.priority = 1

But that forces you to memorize the Value-Name mapping of PRIORITIES. This doesn't work:

thing.priority = 'Normal' # Throws ValueError on .save()

Currently I have this silly workaround:

thing.priority = dict((key,value) for (value,key) in Thing.PRIORITIES)['Normal']

but that's clunky. Given how common this scenario could be I was wondering if anyone had a better solution. Is there some field method for setting fields by choice name which I totally overlooked?

7/13/2009 3:05:15 AM

Accepted Answer

Do as seen here. Then you can use a word that represents the proper integer.

Like so:

LOW = 0
HIGH = 2
    (LOW, 'Low'),
    (NORMAL, 'Normal'),
    (HIGH, 'High'),

Then they are still integers in the DB.

Usage would be thing.priority = Thing.NORMAL

7/13/2009 3:31:43 AM

I'd probably set up the reverse-lookup dict once and for all, but if I hadn't I'd just use:

thing.priority = next(value for value, name in Thing.PRIORITIES
                      if name=='Normal')

which seems simpler than building the dict on the fly just to toss it away again;-).

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow