Using dynamic Choice Field in Django
Asked Answered
C

1

9

I have a choiceField in order to create a select field with some options. Something like this:

forms.py
    class NewForm(forms.Form):
        title = forms.CharField(max_length=69)
        parent = forms.ChoiceField(choices = CHOICE)

But I want to be able to create the options without having a predefined tuple (which is required by ChoiceField). Basically, I need to have access to request.user to fill some options tags according to each user, but I don't know if there is any way to use request in classes of forms.Form.

An alternative would be to prepopulate the instance of NewForm via:

views.py
form = NewForm(initial={'choices': my_actual_choices})

but I have to add a dummy CHOICE to create NewForm and my_actual_choices doesn't seem to work anyway.

I think a third way to solve this is to create a subclass of ChoiceField and redefined save() but I'm not sure how to go about doing this.

Clove answered 21/7, 2012 at 0:9 Comment(0)
D
9

You can populate them dynamically by overriding the init, basically the code will look like:

class NewForm(forms.Form):
    def __init__(self, choices, *args, **kwargs):
        super(NewForm, self).__init__(*args, **kwargs)
        self.fields["choices"] = forms.ChoiceField(choices=choices)

NewForm(my_actual_choices) or NewForm(my_actual_choices, request.POST, request.FILES) etc.

Denunciate answered 21/7, 2012 at 1:19 Comment(4)
I was confused when I saw super() before the constructor, but when I tried it, I got an error: name 'self' is not defined. super() has to be in the constructor. Looking at the edit history, I think that's what Surya meant, as super() was originally the last line in the constructor.Biotechnology
optional, but code might be a little prettier if you just assume 'choices' as a kwarg - as in: blog.eliacontini.info/post/41598616573/…Prioress
This worked for me, but why should I define the fields of the form in the init of the form, instead of searching up the choice values under the form class?Claytonclaytonia
@Claytonclaytonia Right if you're choicefield is already there you can just add your choices like: self.fields['choices'].choices = [(x.pk, x.get_full_name()) for x in User.objects.all()]Denunciate

© 2022 - 2024 — McMap. All rights reserved.