I have to two models, namely Parent and Child. I have managed to make a model form for registering a Parent. Now I want to be able to add a child to the parent.
Expected Outcome: Each parent should have a link that will pull up a child registration form. The Parent Name Field should have initial value of the parent.
I'm currently getting this error,
addChild() missing 1 required positional argument: 'pk
models.py
class Parent(models.Model):
surname = models.CharField(max_length=150, null=False, blank=False)
first_name = models.CharField(max_length=150, null=False, blank=False)
class Child(models.Model):
parent = models.ForeignKey(Parent, null=True, blank=True, on_delete=SET_NULL)
first_name = models.CharField(max_length=50, null=False, blank=False)
last_name = models.CharField(max_length=50, null=False, blank=False)
views.py (What am I missing on my addChild view?)
def addParent(request):
form = ParentForm()
if request.method == 'POST':
form = ParentForm(request.POST, request.FILES)
if form.is_valid():
form.save()
def addChild(request, pk):
parent = Parent.objects.get(id=pk)
form = ChildForm(initial={'parent' :parent})
if request.method == 'POST':
form = ChildForm(request.POST)
if form.is_valid():
form.save()
CodePudding user response:
The pk
URL is supposed to be part of the URL, so you need to update the urlpatterns
to:
path('add_child/<int:pk>/', views.addChild, name='add_child'),
If you thus visit the URL, you should visit add_child/123/
with 123
the primary key of the parent for which you want to add a child.
Since the primary key of the parent is in the URL, it makes not much sense to keep it in the form. You can rewrite the ChildForm
to:
from django import forms
class ChildForm(forms.ModelForm):
class Meta:
model = Child
fields = ['first_name', 'last_name'] # ← no parent
and let the view set the parent when submitting the form:
from django.shortcuts import redirect
def addChild(request, pk):
if request.method == 'POST':
form = ChildForm(request.POST)
if form.is_valid():
form.instance.parent_id = pk
form.save()
return redirect('name-of-some-view')
else:
form = ChildForm(initial={'parent' :parent})
# …
Note: In case of a successful POST request, you should make a
redirect
[Django-doc] to implement the Post/Redirect/Get pattern [wiki]. This avoids that you make the same POST request when the user refreshes the browser.
Note: Functions are normally written in snake_case, not PascalCase, therefore it is advisable to rename your function to
add_child
, not.addChild