I have recently started working with Django and I am struggling to work with 2 models in a single form. I have looked a lot of questions in stackoverflow but I couldn't find any that answers this question.
I have 2 models - Student & Address
This is my models.py
class Students (models.Model):
Student_Name = models.CharField(max_length=50, db_column='Student_Name')
College_Number = models.CharField(
max_length=10, db_column='College_Number')
Gender = models.CharField(max_length=50, db_column='Gender')
Blood_Group = models.CharField(max_length=50, db_column='Blood_Group')
Set = models.CharField(max_length=50, db_column='Set')
Standard = models.CharField(max_length=50, db_column='Standard')
class Addresses (models.Model):
Student_ID = models.ForeignKey(
Students, on_delete=models.CASCADE, db_column='Student_ID')
City = models.CharField(max_length=50, db_column='City')
State = models.CharField(max_length=50, db_column='State')
Pincode = models.CharField(max_length=50, db_column='Pincode')
AddressLine1 = models.CharField(max_length=1024, db_column='AddressLine1')
AddressLine2 = models.CharField(max_length=1024, db_column='AddressLine2')
This is my views.py
def student_create_view(request):
student_form = StudentFrom(request.POST or None)
address_form = AddressForm(request.POST or None)
if (request.POST.get('Student_Name')
and request.POST.get('College_Number')
and request.POST.get('Gender')
and request.POST.get('Blood_Group')
and request.POST.get('Set')
and request.POST.get('Standard')
and request.POST.get('AddressLine1')
and request.POST.get('AddressLine2')
and request.POST.get('City')
and request.POST.get('State')
and request.POST.get('Pincode')
and student_form.is_valid()
and address_form.is_valid()):
# Fetch values from the Student Form
student_form.name = request.POST.get('Student_Name')
student_form.collegenumber = request.POST.get('College_Number')
student_form.Gender = request.POST.get('Gender')
student_form.Blood_Group = request.POST.get('Blood_Group')
student_form.Set = request.POST.get('Set')
student_form.Standard = request.POST.get('Standard')
# Fetch values from the Address Form
address_form.AddressLine1 = request.POST.get('AddressLine1')
address_form.AddressLine2 = request.POST.get('AddressLine2')
address_form.City = request.POST.get('City')
address_form.State = request.POST.get('State')
address_form.Pincode = request.POST.get('Pincode')
student_form.save()
address_form.save()
return redirect('/create')
else:
print(student_form.errors, address_form.errors)
messages.error(request, student_form.errors)
context = {
'student_form': student_form, 'address_form': address_form
}
return render(request, "students/student_create.html", context)
This is my forms.py
from django import forms
from .models import Students, Addresses
SET_CHOICES = (
('Bikrams', 'Bikrams'),
('Ranas', 'Ranas'),
('Aryans', 'Aryans'),
('Rajputs', 'Rajputs')
)
GENDER_CHOICES = (
('Male', 'Male'),
('Female', 'Female')
)
BLOODGROUP_CHOICES = (
('A-Positive', 'A-Positive'),
('AB-Positive', 'AB-Positive'),
('B-Positive', 'B-Positive'),
('O-Positive', 'O-Positive'),
('A-Negative', 'A-Negative'),
('AB-Negative', 'AB-Negative'),
('B-Negative', 'B-Negative'),
('O-Negative', 'O-Negative')
)
STANDARD_CHOICES = (
('Nursery', 'Nursery'),
('KG1', 'KG1'),
('KG2', 'KG2'),
('Class1', 'Class1'),
('Class2', 'Class2'),
('Class3', 'Class3'),
('Class4', 'Class4'),
('Class5', 'Class5'),
('Class6', 'Class6'),
('Class7', 'Class7'),
('Class8', 'Class8'),
('Class9', 'Class9'),
('Class10', 'Class10'),
('Class11', 'Class11'),
('Class12', 'Class12')
)
class StudentFrom(forms.ModelForm):
Set = forms.ChoiceField(choices=SET_CHOICES,
widget=forms.RadioSelect(attrs={'class': 'ml-2'}))
Gender = forms.ChoiceField(
choices=GENDER_CHOICES, widget=forms.RadioSelect(attrs={'class': 'ml-2'}))
Blood_Group = forms.ChoiceField(choices=BLOODGROUP_CHOICES)
Standard = forms.ChoiceField(choices=STANDARD_CHOICES)
class Meta:
model = Students
fields = ['Student_Name', 'College_Number',
'Gender', 'Blood_Group', 'Set', 'Standard']
class AddressForm(forms.ModelForm):
AddressLine1 = forms.CharField(label='Address Line 1', widget=forms.Textarea(
attrs={'rows': '1', 'cols': '35'}))
AddressLine2 = forms.CharField(label='Address Line 2', widget=forms.Textarea(
attrs={'rows': '1', 'cols': '35'}))
class Meta:
model = Addresses
fields = ['AddressLine1',
'AddressLine2', 'City', 'State', 'Pincode']
I am successfully able to migrate this to mysql db and I can see the foreign key relation(1 Student can have many Address) in Django admin. However, I am trying to populate both the models using a single form and I am unable to do that because I am not sure how to set my foreign key value(Student_ID) in Addresses.
Looking for a solution where I can populate the Student_ID foreign key field in *Addresses with the primary key value in Student (which is the default primary key created by Django) model.
Is there a way to automatically do that so that I don't have to handle this in the template ?
You can obtain the result of the student_form.save()
and assign it to the Student_ID
of the .instance
wrapped in the address_form
:
def student_create_view(request):
if request.method == 'POST':
student_form = StudentFrom(request.POST)
address_form = AddressForm(request.POST)
if student_form.is_valid() and address_form.is_valid():
# Fetch values from the Student Form
student = student_form.save()
address_form.instance.Student_ID = student
address_form.save()
return redirect('/create')
else:
print(student_form.errors, address_form.errors)
messages.error(request, student_form.errors)
else:
student_form = StudentFrom()
address_form = AddressForm()
context = {
'student_form': student_form, 'address_form': address_form
}
return render(request, "students/student_create.html", context)
Normally a ForeignKey
does not end with _ID
, you thus might want to rename the field to student
(field names are written in snake_case
not ), and thus write this as:PascalCase
address_form.instance.student = student