Save ForeignKey on post in django

Question:

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
Asked By: Farid

||

Answers:

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.

Answered By: Willem Van Onsem
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.