Papouche Guinslyzinho
Papouche Guinslyzinho

Reputation: 5458

How to save parent objects within the form_valid

I have a class based view. I am trying to save an object with it's association. I have the following error :

NOT NULL constraint failed: boxes_suggestion.box_id

More explanation: I have a SuggestionBox (Model) and each Participant could add Comments into it. it's sort of a doodle clone.

detail.html

        <h3>{{box.title}}</h3>

<form action="." method="post">{% csrf_token %}
    {{ form.as_p }}
     <input id="box_id_value" type="hidden" name="box_id_value" value='{{box.id}}' />
    <input type="submit" class="btn btn-info" value="Add suggies 1" />
</form>

views.py

class SuggiesForm(FormView):
    '''
    Display the form
    Otherwise
    Process the form
        1-Get the suggestion_box_id
        2-Save the comment associated with that suggestion box.
    '''
    template_name = 'boxes/detail.html'
    form_class = SuggestionForm
    success_url = '/boxes/success'
    box_instance = ''

    def get_context_data(self, **kwargs):
       '''
       Retrieve the id of the Suggestion Box
       '''
       context = super(SuggiesForm, self).get_context_data(**kwargs)
       #Find The appropriate Box so that user can add Suggies
       context['box'] = Box.objects.get(pk=self.kwargs['pk'])
       box_instance = context['box']
       return context

    def form_valid(self, form):
        '''

        '''
        form.save(commit=False)
        #box = box_instance  
        form.box = Box.objects.first()
        form.participant = Suggestion.objects.first()
        form.save()
        return super(SuggiesForm, self).form_valid(form)

models.py

@python_2_unicode_compatible
class Box(models.Model):
    """
    Box model
    """
    def __str__(self):
        return self.title
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)     
    title = models.CharField(max_length=40, blank=True, null=True)
    identify = models.BooleanField(default=False)
    activate = models.BooleanField(default=False)
    created_at = models.DateField(auto_now_add=True)
    updated_at = models.DateField(auto_now=True)
    #expiration_date = models.DateField(auto=Date in Future, blank=True, null=False)
    #slug = AutoSlugField(_('slug'), populate_from="id")
    #url(slug)

@python_2_unicode_compatible
class Participant(models.Model):
    """
    Participant Model
    """
    def __str__(self):
        return  self.email

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)     
    email = models.EmailField(blank=True, null=True, default='[email protected]')
    username = models.CharField(max_length=40, blank=True, null=True)
    box = models.ForeignKey(Box, on_delete=models.CASCADE)
    created_at = models.DateField(auto_now_add=True)
    updated_at = models.DateField(auto_now=True)

@python_2_unicode_compatible
class Suggestion(models.Model):
    """
    For adding comments (or suggestions)
    """
    def __str__(self):
        return self.comment[0:10]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)     
    comment = models.CharField("",max_length=250, blank=True, null=True)
    box = models.ForeignKey(Participant, on_delete=models.CASCADE)
    created_at = models.DateField(auto_now_add=True)
    updated_at = models.DateField(auto_now=True)

Upvotes: 0

Views: 134

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599630

You correctly used commit=False, but then added the attributes onto the form object itself instead of the object returned from the save. It should be:

    object = form.save(commit=False)
    object.box = Box.objects.first()
    object.participant = Suggestion.objects.first()
    object.save()

Upvotes: 1

Related Questions