Django form with m2m relationship not saving

Question:

I have a form where I want request.user to populate as little as possible and rely on the views to populate other fields automatically.

As a result, some of these fields are not rendered on the form.

The code in my view seems to work fine for the FK relationship, but some reason the m2m is failing.

It’s probably the first time I am trying to save a form with m2m and I am probably missing something.

At the moment the error I get with the current code is 'VoucherForm' object has no attribute 'user'.

If I remove voucherform.user.add(userprofile)from the views the form will save, but will not add the user.

model

class UserProfile(models.Model):
    user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)

class Voucher(models.Model):
    user = models.ManyToManyField(User, blank=True)
    venue = models.ForeignKey(Venue, blank=True, null=True, related_name="vouchervenues", on_delete=models.CASCADE)
    title = models.TextField('voucher title', blank=True)
    terms = models.TextField('terms & conditions', blank=True)

form

class VoucherForm(ModelForm):
    class Meta:
        model = Voucher
        fields = ('title','terms')
        labels ={

            'title': '',
            'terms': '',

        }
        widgets = {

                    'title': forms.TextInput(attrs={'class':'form-control', 'placeholder':'Enter title'}),
                    'terms': forms.TextInput(attrs={'class':'form-control', 'placeholder':'Enter terms'}),
                   
                }

views

def add_voucher(request, userprofile_id):
    url = request.META.get('HTTP_REFERER')
    venue = UserProfile.objects.filter(user=request.user).values('venue')
    userprofile = UserProfile.objects.get(id=userprofile_id)
    
    submitted = False
    if request.method =="POST":
        voucherform = VoucherForm(request.POST)
        if voucherform.is_valid():
            data = voucherform.save(commit=False)
            data.user_id = userprofile.id
            data.venue_id = venue
            data.save()
            voucherform.save_m2m()
            voucherform.user.add(userprofile)
            return HttpResponseRedirect(url)
    else:
        voucherform = VoucherForm
        if 'submitted' in request.GET:
            submitted=True
    return redirect('venue-loyalty-card',{'submitted':submitted,'userprofile':userprofile})
Asked By: PhilM

||

Answers:

Basically, the problem is that you haven’t mentioned user field in VoucherForm at fields so it says ‘VoucherForm’ object has no attribute ‘user’, you can do the following:

from django.shortcuts import get_object_or_404

def add_voucher(request, userprofile_id):
    url = request.META.get('HTTP_REFERER')
    venue = UserProfile.objects.filter(user=request.user).values('venue')
    userprofile = UserProfile.objects.get(id=userprofile_id)
    
    submitted = False
    if request.method =="POST":
        voucherform = VoucherForm(request.POST)
        if voucherform.is_valid():
            data = voucherform.save(commit=False)
            data.user_id = userprofile.id
            data.venue_id = venue
            data.save()
            voucherform.save_m2m()
            current_voucher_instance= get_object_or_404(Voucher,id=data.id)
            current_voucher_instance.user.add(userprofile.id)
            return HttpResponseRedirect(url)
    else:
        voucherform = VoucherForm
        if 'submitted' in request.GET:
            submitted=True
    return redirect('venue-loyalty-card',{'submitted':submitted,'userprofile':userprofile})

Note: It is better to use get_object_or_404() than get() as it calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.

Answered By: Sunderam Dubey