Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

addChild() missing 1 required positional argument: 'pk

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,

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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()

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading