0

I've got a ModelForm that I've modified such that it returns a tuple for an option group multiselect on the displayed form. Tuple is structured like this:

(
 ('Alabama', (
  ('1', 'Item 1'),
  ('2', 'Item 2'),
  )
 ),
 ('Alaska', (
  ('3', 'Item 3'),
  ('4', 'Item 4'),
  )
 ),
)

The problem I've run into is that the underlying data that makes up the contents of the choices tuple might change (Item 5 might be added or Item 4 may be deleted) but the tuple never gets updated - presumably because Django knows tuples are immutable and my get_tree_data() function never gets called after the server starts for the first time. How do I override that behavior? My code is below:

def get_tree_data():
    sp = StateProvince.objects.all().values('state_province').order_by('state_province')
    my_dict = OrderedDict()
    for i in sp:
       for k in Location.objects.filter(state_province__state_province=i['state_province']):
           try: my_dict[i['state_province']].append([k.id, k.name])
           except KeyError: my_dict[i['state_province']] = [[k.id, k.name]]
    return tuple([(key, tuple([(a, b) for a, b in value])) for key, value in my_dict.iteritems()])


class SchedulerProfileForm(ModelForm):
    locations = MultipleChoiceField(choices=get_tree_data())
    class Meta:
        model = SchedulerProfile

EDIT Per the accepted answer, code:

class SchedulerProfileForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(SchedulerProfileForm, self).__init__(*args, **kwargs)
        self.fields['locations'] = MultipleChoiceField(choices=get_tree_data())

class Meta:
    model = SchedulerProfile
ghiotion
  • 285
  • 5
  • 12
  • 1
    this doesn't answer your question, but you should read: http://stackoverflow.com/a/960753/403423 – rbp Feb 01 '15 at 16:23
  • the defaultdict is great, but i also need it ordered... i know there are recipes out there for ordered default dicts but... i don't know. lots of extra LOC to convert two try/except lines into one line. i'm sure defaultdict is more performant tho. – ghiotion Feb 01 '15 at 19:28
  • there's a very nice one right here on StackOverflow.SE! http://stackoverflow.com/a/4127426/403423 – rbp Feb 01 '15 at 19:31

1 Answers1

1

The declaration of a class as well as its fields is interpreted at import time, so does the initialization of the choices value.

What you can do, is define __init__ function for SchedulerProfileForm where you initialize locations field by calling get_tree_data() inside.

EDIT: Or, inherit from MultipleChoiceField and redefine __init__ there.

Andrew_Lvov
  • 4,621
  • 2
  • 25
  • 31