Home > Net >  addChild() missing 1 required positional argument: 'pk
addChild() missing 1 required positional argument: 'pk

Time:12-20

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.

  • Related