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)]
Good job! Thanks for the good information.