Saving related model objects in single view

Issue

I am beginner and I am working on Django project – risk assessment application.

I have a trouble to achieve saving on related objects for my application risk record. I am using MultiModelForm to achieve the following.

I am successfully creating Whatif instance and connecting it with GuideWordi instance on save, however, I am not able to connect my RiskRecordi instance with GuideWordi instance, but RiskRecordi instance is saved into the db (I see it through admin).
I tried lot’s of research over the web, but confused now.

My models.py:

class WhatIf(models.Model):
   moc_no = models.CharField(max_length=12, blank=True)
   ra_scope = models.TextField(max_length=128, blank=True)
   facilitator = models.ForeignKey(User, related_name='facilitator', 
   null=False, on_delete=models.SET_DEFAULT, default='0')
     
    
   def __str__(self):
      return self.moc_no
    
   def get_absolute_url(self):
      return reverse('whatif:whatif_form', kwargs={'pk': self.pk})


class GuideWordi(models.Model):
    whatif = models.ForeignKey(WhatIf, blank=True, on_delete=models.CASCADE)
    name = models.CharField(max_length=160, blank=True)

    def __str__(self):
        return self.name


class RiskRecordi(models.Model):
    guidewordi = models.ForeignKey(GuideWordi, blank=True, null=True, on_delete=models.CASCADE)
    cause = models.TextField(max_length=128, blank=True)
    consequence = models.TextField(max_length=128, blank=True)
    safeguard = models.TextField(max_length=128, blank=True)

My views.py

class WhatIfCreateView(CreateView):
    Model = WhatIf
    form_class = WhatIfForm
    template_name = 'whatif/ra-initiate.html'

    def form_valid(self, form):
         
        obj = form.save(commit=False)
        obj.facilitator = self.request.user
        return super().form_valid(form)



from multi_form_view import MultiModelFormView

class RiskRecordView(MultiModelFormView):
    
    form_classes = {
        'guideword_form' : GuideWordiForm,
        'riskrecord_form' : RiskRecordiForm,}
        
    template_name = 'whatif/create-record.html'


    def forms_valid(self, forms):
        
        forms['guideword_form'].instance.whatif_id = self.kwargs['pk']

        guideword = forms['guideword_form'].instance.save()

        forms['riskrecord_form'].instance.guidewordi_id = self.kwargs['pk']

        riskrecord = forms['riskrecord_form'].save()

        return super(RiskRecordView, self).forms_valid(forms)
        
    def get_success_url(self):
        return reverse_lazy('whatif:whatif_form', kwargs={'pk': self.kwargs['pk']})

Here are my partial view of my guideword & riskrecord submit page template which I submit together from same page (it is not full code here).

<td rowspan=3 height=72 class=xl17118545 width=359 style='height:80.0pt; width:269pt'>{{ forms.guideword_form.name }}</td>
<td rowspan=3 class=xl16618545 width=251 style='width:188pt'>{{ forms.riskrecord_form.cause }}</td>
<td rowspan=3 class=xl16318545 width=235 style='width:177pt'>{{ forms.riskrecord_form.consequence }}</td>
<td rowspan=3 class=xl16318545 width=272 style='width:204pt'>{{ forms.riskrecord_form.safeguard }}</td>

My forms.py:

class WhatIfForm(forms.ModelForm):
    class Meta:
        model = WhatIf
        fields = ('moc_no', 'ra_scope',)

class GuideWordiForm(forms.ModelForm):
    class Meta:
        model = GuideWordi
        fields = ('name',)


class RiskRecordiForm(forms.ModelForm):
    class Meta:
        model = RiskRecordi
        fields = ('cause', 'consequence', 'safeguard',)

Solution

You should check what values get saved and then debug(print) the relevant variables.

The self.kwargs['pk'] part seems kinda odd.

I don’t use MultiModelFormView but logic seems to be the same, so you could:

def forms_valid(self, forms):

  # save new guideword obj
  guideword = forms['guideword_form'].save() 

  #save but donĀ“t commit -> get the riskrecord obj 
  riskrecord = forms['riskrecord_form'].save(commit=False) 

  # now add the guideword obj to the riskrecord obj
  riskrecord.guidewordi = guideword

  #save to db
  riskrecord.save() 

Answered By – David Wenzel

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published