How to save two models with a parent and child relationship simultaneously

Hi everyone,

I have 2 models(Riskassessment and Goal) that have a many to one relationships. I use a form for the riskassessment and a formset within that form for the goal. I wonder how to get the pk of the current riskassessment(the parent) into the formset(child) and be able to save both (formset and form) with one submit.
I haven’t add the jquery yet as I am still worry about saving the 2 objects
Please can you help me.
Here follow my files

models.py

class Customer(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    email = models.EmailField(blank=True)


class RiskAssessment(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="riskassessment", null=True)
    support_in_communicating = models.BooleanField(editable=True, default=False)
    supp_comm_comment = models.TextField(blank=True, max_length=50)
    communication_aids = models.BooleanField(editable=True, default=False)


class Goal(models.Model):
    riskassess = models.ForeignKey(RiskAssessment, on_delete=models.CASCADE, name='riskassess', blank=True, null=True)

    class Choice(models.TextChoices):
        stomp = 'stomp', _('STOMP')
        medprof = 'medication profile', _('Medication profile')
        medsup = 'medication support', _('Medication support')
        heathact = 'health action', _('Health action')
        menthealth = 'mental health', _('Mental health and well being')
        physhealth = 'hysical health', _('Physical health')
        parentskills = 'parenting skills', _('Parenting skills')

    # [...]
    choice = models.CharField(
        max_length=30,
        choices=Choice.choices,
        default=Choice.medprof,
    )

    task = models.TextField(max_length=100)
    due_date = models.DateField(null=True)
    active = models.BooleanField(editable=True, default=False)
    recurrent = models.BooleanField(editable=True, default=False)
    done = models.BooleanField(editable=True, default=False)

    def __str__(self):
        return "%s %s %s %s" % (self.Choice, self.task, self.due_date, self.recurrent, self.done)

forms.py

class RiskAssessmentForm(forms.ModelForm):
    class Meta:
        model = RiskAssessment
        
        fields = ['customer', 'support_in_communicating', 'supp_comm_comment', 'communication_aids']

        def __init__(self, *args, user, **kwargs):
        super(RiskAssessmentForm, self).__init__(*args, **kwargs)
        self.fields['customer'] = forms.ModelChoiceField(queryset=Customer.objects.filter(author=user))
    CHOICES = ((0, 'Please select a choice'), (1, 'STOMP'), (2, 'Medication profile'), (3, 'Mediaction support'),
               (4, 'Hospital passport'), (5, 'Health action plan'), (6, 'Mental health and well being'),
               (7, 'Physical health'), (8, 'Parenting skills'), (9, 'Healthy relationships'),
               (10, 'Developing interest'),
               (11, 'Improving reading, writing and IT sills'), (12, 'Gaining qualifications'),
               (13, 'Education, training and employement'), (14, 'Benefit'), (15, 'Budgeting and money management'),
               (16, 'Reduction in offending'), (17, 'Moving on'), (18, 'Communication plan'))

    riskassess = forms.ModelChoiceField(queryset=RiskAssessment.objects.all())
    choice = forms.MultipleChoiceField(required=False, choices=CHOICES)
    task = forms.CharField(widget=forms.Textarea)
    due_date = forms.DateField()
    active = forms.BooleanField()
    recurrent = forms.BooleanField()
    done = forms.BooleanField()

    def save(self, *args, **kwargs):
        riskassessment = super().save(*args, **kwargs)
        Goal.objects.create(
            riskassess=riskassessment,
            choice=self.cleaned_data['choice'],
            task=self.cleaned_data['task'],
            due_date=self.cleaned_data['due_date'],
            active=self.cleaned_data['active'],
            recurrent=self.cleaned_data['recurrent'],
            done=self.cleaned_data['done'],

        )
        return riskassessment


class GoalForm(forms.ModelForm):

    class Meta:
        model = Goal
        exclude = ['riskassess']
    fields = ['choice', 'task', 'due_date', 'active', 'recurrent', 'done']


GoalFormSet = formset_factory(form=GoalForm, extra=1)

views.py

def add_riskassessment(request):

    if request.method == 'POST':
        form = RiskAssessmentForm(request.POST, user=request.user)
        goalset = GoalFormSet(request.POST, prefix='goal')

        if form.is_valid() and goalset.is_valid():
            form.save()

            goalset.save()

            messages.success(request, f'Your form has been created!')
            return redirect('addriskassessment')
    else:
        form = RiskAssessmentForm(user=request.user)
        goalset = GoalFormSet()
    return render(request, 'app/addriskassessment.html', {'form': form, 'goalset': goalset})

addriskassessment.html


<h1>Risk Assessment Form</h1>
                    <fieldset class="flex-container">
                        <div class="form-group row">

                            <label >Customer</label>
                            <div class="col-md-4">
                                {{form.customer}}
                            </div>
                        </div>
                        <div class="form-group row">
                            <h2>Communication</h2>
                        </div>

                            <div class="form-group row">
                                <label>Support communication</label>
                                <div class="col-md-4 " >
                                {{form.support_in_communicating}}
                                </div>
                            </div>
                            <div class="form-group row">
                                <label >Commentary</label>
                                {{form.supp_comm_comment}}
                            </div>
                            <div class="form-group row">
                                <label>Communication Aids</label>
                                <div class="col-md-4">
                                  {{form.communication_aids}}
                                </div>
                            </div>
                            <div>
                                {{ formset.management_form }}
                                <label>Choice: {{form.choice}}</label>
                                <label>Task to do: {{form.task}}</label>
                                <label>Due date: {{form.due_date}}</label>
                                <label>Active {{form.active}}</label>
                                <label>Recurrence {{form.recurrent}}</label>
                                <label>Task is done {{form.done}}</label>



                            </div>
                    </fieldset>

Thank you

This is covered by the Saving objects in the formset section of the docs. You might also want to review the save() method on forms.

Ken