6

I am creating a form that uses MultipleChoiceField. The values for this field are derived from another model. This method works fine, however, I am noticing (on the production server) that when I add a new item to the model in question (NoticeType), the form does not dynamically update. I have to restart the server for the new item to show up on my MultipleChoiceField.

Any changes to the NoticeType model (editing items or creating new ones) do not propagate to the form. After I restart the production server, the updates appear.

Any ideas why this might be ? The relevant portion of the form is below. Thanks.

from django import forms 
from django.contrib.auth.models import User
from notification.models import NoticeType

class EditUserProfileForm(forms.Form):   
    CHOICES = []

    for notice in NoticeType.objects.all():
        CHOICES.append( (notice.label,notice.display) )

    notifications   = forms.MultipleChoiceField(
                        label="Email Notifications",
                        required=False,
                        choices=( CHOICES ),
                        widget=forms.CheckboxSelectMultiple,)

2 Answers 2

9

Although mherren is right that you can fix this problem by defining your choices in the __init__ method, there is an easier way: use the ModelMultipleChoiceField which is specifically designed to take a queryset, and updates dynamically.

class EditUserProfileForm(forms.Form):
    notifications = forms. ModelMultipleChoiceField(
                    label="Email Notifications",
                    required=False,
                    queryset = NoticeType.objects.all(),
                    widget=forms.CheckboxSelectMultiple)
Sign up to request clarification or add additional context in comments.

5 Comments

That is even sexier! And I thought it couldn't get any better - thanks for that. Will be making that adjustment saving some precious space in my codebase. Thanks.
Using this technique would I still be able to specify which model field is shown as the "text" on the form?
By default it uses the __unicode__ representation. If you need something different, you'll need to subclass ModelMultipleChoiceField and override label_from_instance, as described here: docs.djangoproject.com/en/dev/ref/forms/fields/…
Thanks - I think I may go that route because, I assume, it seems to be the way "the django" wants it. I am new to stackoverflow - should I post my final "working" code as an "answer" after I am done?
@DanielRoseman thank you for label_from_instance! Helped a lot.
7

My hunch is that the class definition is only being processed once on load rather than for each instantiation. Try adding the CHOICES computation to the init method like so:

def __init__(self, *args, **kwargs):
    super(self.__class__, self).__init__(*args, **kwargs)
    CHOICES = []
    for notice in NoticeType.objects.all():
        CHOICES.append( (notice.label, notice.display) )
    self.fields['notifications'].choices = CHOICES

1 Comment

Hey! Great - that fixed it immediately. After I posted I had a similiar thought, actually, but wasn't thinking about the __init__() method ... I thought I could create a new function outside the class that returned the list ... but I like this even better. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.