Hi I am having trouble with saving a fk in Infringer table on post. I am trying to save the customer ID when I add a record. For troubleshoot purposes I added a few print lines and this the out put. As you can see below the correct customer ID is present but the customer is None so its not being saved into the record. The other fields save fine. PLEASE HELP! I am a beginner.
customer in forms.py is 2
forms.py instance was saved with the customer None
customer in views.py is 2
Successfully saved the infringer in views.py with its customer None
views.py
@login_required(login_url='login') def createInfringer(request): customer=request.user.customer.id form = InfringerForm(customer=customer) if request.method == 'POST': form = InfringerForm(customer, request.POST) if form.is_valid(): saved_instance = form.save(customer) print (f'customer in views.py is {customer}') print (f'Successfully saved the infringer in views.py with its customer {saved_instance.customer}') return redirect('infringer-list') context ={'form': form} return render (request, 'base/infringement_form.html', context)
forms.py
class InfringerForm(ModelForm): class Meta: model = Infringer fields = ['name', 'brand_name','status'] def __init__(self, customer, *args, **kwargs): super(InfringerForm,self).__init__(*args, **kwargs) self.fields['status'].queryset = Status.objects.filter(customer=customer) def save(self, customer, *args, **kwargs): instance = super(InfringerForm, self).save( *args, **kwargs) if customer: print (f'customer in forms.py is {customer}') self.customer = customer instance.save() print (f' forms.py instance was saved with the customer {instance.customer}') return instance
models.py
class Infringer (models.Model): name = models.CharField(max_length=200) brand_name = models.CharField(max_length=200, null=True) updated = models.DateTimeField(auto_now=True) created = models.DateTimeField(auto_now_add=True) status = models.ForeignKey(Status, on_delete=models.SET_NULL,null=True) customer = models.ForeignKey(Customer, on_delete=models.SET_NULL,null=True) class Meta: ordering = ['-updated', '-created'] def __str__(self): return self.name
CodePudding user response:
It might help to simplify your form, for example with:
class InfringerForm(ModelForm):
class Meta:
model = Infringer
fields = ['name', 'brand_name', 'status']
def __init__(self, customer, *args, **kwargs):
super().__init__(*args, **kwargs)
self.customer = customer
self.fields['status'].queryset = Status.objects.filter(customer=customer)
def save(self, *args, **kwargs):
self.instance.customer = self.customer
return super().save( *args, **kwargs)
With that done, we can also simplify the view logic to:
@login_required(login_url='login')
def createInfringer(request):
customer = request.user.customer
form = InfringerForm(customer=customer)
if request.method == 'POST':
form = InfringerForm(customer, request.POST, request.FILES)
if form.is_valid():
saved_instance = form.save()
print (f'customer in views.py is {customer}')
print (f'Successfully saved the infringer in views.py with its customer {saved_instance.customer}')
return redirect('infringer-list')
return render (request, 'base/infringement_form.html', {'form': form})
So we use the customer, not its primary key, and we do not have to pass the customer in the .save()
method anymore.