Dynamic ModelMultipleChoice In Django

Published: Aug. 18, 2017, 8:49 p.m. Back

Author: rachell

I needed to create a django form on an existing project that registered new users to the system and added them to specific site_groups, not the built in groups that django has. 

So in theory, in my forms.py, I wanted to do:

class AddUserForm(forms.Form):
email = forms.EmailField(...)
password = forms.CharField(...)
site_group = forms.ModelMultipleChoiceField(queryset=SiteGroup.objects.filter(site=request.site))

 

But you can see the problem with getting request.site before the form is even creating. 

So while doing research, I came across this site, Simple is Better than Complex. I've actually come across that site quite a bit for different situations and I love his simple explanations and code exmaples. So I understood I'd have to send a variable from my views.py, but instead of 'user' it would be the 'site'. So that brought me to: 

 

class AddUserForm(forms.Form):
email = forms.EmailField(...)
password = forms.CharField(...)
site_group = forms.ModelMultipleChoiceField(queryset=None)

def __init__(self, site, *args, **kwargs):
super(AddUserForm, self).__init__(*args, **kwargs)
self.fields['site_group'].queryset = SiteGroup.objects.filter(site=site)
self.fields['site_group'].choices = [(i.id, i.name) for choices in SiteGroup.objects.filter(site=site)]

In my template, I had something similar to this:

{% for group in form.site_group.field.choices %}
<li>
<label for="id_site_group_{{ forloop.counter0 }}">
<input id="id_site_group_{{ forloop.counter0 }}" name="site_group" type="checkbox" value="{{ group.0 }}"> {{ group.1 }}</label>
</li>
{% endfor %}

But because I wasn't getting exactly what I wanted for group.1 for the label of all the choices, I decided to customize them. Using the same logic as above I created my own choices. Adding this line of code at the bottom of the previous example will let you get specific fields you want for labeling your form fields. 

self.fields['site_group'].choices = [(i.id, i.name) for choices in SiteGroup.objects.filter(site=site)]

 

So be it 'site' or 'user' or any other variable you need to pass through to your forms to use as a queryset, this example will help you get there, with custom labeling. 
 
Happy Forming! 


Sept. 26, 2017, 5:01 a.m.
aman

Good job! Thanks for the good information.

New Comment