Question

I have the following model:

class UserProfile(models.Model):

user = models.OneToOneField(User, related_name="user")
people_interested = models.ManyToManyField(User, related_name="interested")

Now I want a form where I want to offer users a form where they can choose people_interested, so I add the following forms.py

class ChooseForm(forms.Form):
    q_set = User.objects.all()
    peers = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset = q_set)

and then in views:

form = ChooseForm(data = request.POST or None)
if request.POST and form.is_valid():
    uprofile, created = UserProfile.objects.get_or_create(user=request.user)
    uprofile.people_interested = form.cleaned_data['peers']
    uprofile.save()
    return HttpResponseRedirect("/")
else:
    return render(request, "form_polls.html", {'form':form})

But the trouble with this is, the current user instance also gets displayed. So I tried the following in views.py:

form = ChooseForm(request.user.id, data = request.POST or None)

and then in forms.py

class ChooseForm(forms.Form):

    def __init__(self, uid, *args, **kwargs):
        super(ChooseForm, self).__init__(*args, **kwargs)
        self.fields['peers'].queryset = User.objects.exclude(id=uid)
    q_set = User.objects.all() 
    peers = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset = q_set)

But the above is not a clean implementation, is there a better method of doing it??

Was it helpful?

Solution

What makes you say this is not a clean implementation? Overwriting queryset on __init__ is perfectly acceptable.

The only things I'd do to improve your code is using a post_save signal on User to create it's UserProfile, then just do user.get_profile() on your view. See this question

You could also use a ModelForm for UserProfile instead of a regular form, and limit the fields to people_interested.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top