Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django model field choices - wouldn't a dict be better?

Given a field;

domain_status_choices = (
    (1,'Live')
    (2,'Offline')
    (3,'Dev')
)
status = models.SmallIntegerField( choices=domain_status_choices )

I know I can get and set numeric representation and use get_status_display() to get the text label. But if a user posts status=Offline how can I get the numeric value in order to save it? I'd also like to be able to validate that numbers or text values are in the list.

To me it makes more sense to use a dict. Here's my current method;

domain_status_choices = {
    1: 'Live',
    2: 'Offline',
    3: 'Dev',
}
status = models.SmallIntegerField( choices=domain_status_choices.iteritems() )
...
if input1 not in domain_status_choices.keys(): print "invalid"
if input2 not in domain_status_choices.items(): print "invalid"
status = [k for k, v in domain_status_choices.iteritems() if v == input3][0]

Is there a better way? Why is a tuple of tuples usually used?

like image 801
Jake Avatar asked Jan 15 '11 09:01

Jake


2 Answers

I believe the keys of a dict are not guaranteed to be sorted (unless you use OrderedDict obviously). That is, you "might" get "Offline", "Dev", "Live" choices with your version.

Implementation note on dict.items:

Keys and values are listed in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions.

like image 190
vicvicvic Avatar answered Oct 07 '22 19:10

vicvicvic


Expanding on my comment on @vicvicvic's answer:

t = [ 'Live', 'Offline', 'Dev', ]
status = models.SmallIntegerField( choices=[(i,t[i]) for i in range(len(t))] )
...
if not 0 <= int(input1) < len(t): print "invalid"
if input2 not in t: print "invalid"
status = t.index(input2)
like image 36
Jake Avatar answered Oct 07 '22 17:10

Jake