I have the below two models
# models.py
class Applicant(models.Model):
"""
A table to store all applicants, relates 1-n to an offer
"""
name = models.CharField(max_length=50)
job = models.CharField(max_length=50)
start = models.DateField(null=True, blank=True)
def __str__(self):
return f'{self.name} applying for {self.job} starting {self.start}'
class Offer(models.Model):
"""
A table to store created offers
"""
# Relations
applicant = models.ForeignKey(Applicant, on_delete=models.CASCADE)
# Self
monthly_raise = models.FloatField()
months = models.PositiveIntegerField(validators=[MinValueValidator(1), MaxValueValidator(60)])
start_salary = models.FloatField()
In my template I render all fields except for start (which I don’t render at all) in the same <form></form> wrapper. Now in my view I want to create new instances for each of the modelforms but only if both are valid.
This is what I have which throws
NOT NULL constraint failed: planner_offer.applicant_id
def render_dashboard_planner(request):
site = 'planner'
if request.method == 'GET':
applicant_form = ApplicantForm()
offer_form = OfferForm()
context = {
'applicant_form': applicant_form,
'offer_form': offer_form,
'site': site
}
return render(request, "dashboard/dashboard_planner.html", context)
else:
# Process the created Offer
applicant_form = ApplicantForm()
offer_form = OfferForm()
form_applicant = ApplicantForm(request.POST)
form_offer = OfferForm(request.POST)
if form_applicant.is_valid() and form_offer.is_valid():
# Grab the data
form_applicant.save(commit=True)
# Create Offer instance
form_offer.save(commit=False)
form_offer.applicant = form_applicant
form_offer.save(commit=True)
context = {
'site': site,
'offer_form': offer_form,
'applicant_form': applicant_form,
}
return render(request, "dashboard/dashboard_planner.html", context)
How would I fix the relation issue and is this a proper way to handle the workflow in that manner at all?
Advertisement
Answer
You should set the .applicant on the .instance of the form, and use the instance of the form_applicant, not the form_applicant itself, so:
from django.shortcuts import redirect
def render_dashboard_planner(request):
site = 'planner'
if request.method == 'POST':
form_applicant = ApplicantForm(request.POST, request.FILES)
form_offer = OfferForm(request.POST, request.FILES)
if form_applicant.is_valid() and form_offer.is_valid():
# Grab the data
applicant = form_applicant.save()
form_offer.instance.applicant = applicant
form_offer.save()
return redirect('name-of-some-view')
else:
applicant_form = ApplicantForm()
offer_form = OfferForm()
context = {
'applicant_form': applicant_form,
'offer_form': offer_form,
'site': site
}
return render(request, 'dashboard/dashboard_planner.html', context)