Reputation: 283293
I've got some <selects>
that I need to populate with some choices
that depend on the currently logged in user. I don't think this is possible (or easy) to do from inside the form class, so can I just leave the choices blank and set them in the view instead? Or what approach should I take?
Upvotes: 9
Views: 10402
Reputation: 1
Forms.py
class MyForm(forms.Form):
""" Initialize form values from views"""
select=forms.BooleanField(label='',required=False)
field_1=forms.CharField(label='',widget=forms.TextInput(attrs= \
{'size':'20','readonly':'readonly',}))
field_2=forms.ChoiceField(widget=forms.Select(), \
choices=((test.id,test.value) for test in test.objects.all()))
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
input=kwargs.get('initial',{})
get_field_1_initial_input_from_views=re.sub("\[|\]|u'|'","",str (input.values()))
# override field_2 choices based on field_1 input
try:
# filter choices
self.fields[‘field_2'].choices=((test.id,test.value) for test in test.objects.filter ( --------)))
except:
pass
Views.py
def views_function(request,val):
"""Dynamically generate input data for formset."""
Initial_data=[]
initial_data.append({'field_1':data.info})
#Initializing formset
MyFormSet=formset_factory(MyForm,extra=0)
formset=MyFormSet(initial=initial_data)
context={'formset':formset}
if request.method == 'POST':
formset=MyFormSet(request.POST,request.FILES)
if formset.is_valid():
# You can work with the formset dictionary elements in the views function (or) pass it to
#Forms.py script through an instance of MyForm
return HttpResponse(formset.cleaned_data)
return render_to_response(‘test.html', context,context_instance=RequestContext(request))
Upvotes: 0
Reputation: 29420
You could build your form dynamically in you view (well, actually i would rather keep the code outside the view in it's own function and just call it in the view but that's just details)
I did it like this in one project:
user_choices = [(1, 'something'), (2, 'something_else')]
fields['choice'] = forms.ChoiceField(
choices=user_choices,
widget=forms.RadioSelect,
)
MyForm = type('SelectableForm', (forms.BaseForm,), { 'base_fields': fields })
form = MyForm()
Obviously, you will want to create the user_choices
depending on current user and add whatever field you need along with the choices, but this is a basic principle, I'll leave the rest as the reader exercise.
Upvotes: 2
Reputation: 2968
Considering that you have included the user as a parameter, I would solve this using a custom tag.
In your app/templatetags/custom_tags.py something like this:
@register.simple_tag
def combo(user, another_param):
objects = get_objects(user, another_param)
str = '<select name="example" id="id_example">'
for object in objects:
str += '<option value="%s">%s</option>' % (object.id, object.name)
str += '</select>'
return mark_safe(str)
Then in your template:
{% load custom_tags %}
{% special_select user another_param %}
More about custom tags http://docs.djangoproject.com/en/dev/howto/custom-template-tags/
Upvotes: 1
Reputation: 4403
Not sure if this is the best answer, but in the past I have set the choices of a choice field in the init of the form - you could potentially pass your choices to the constructor of your form...
Upvotes: 5