简体   繁体   中英

Django NOT NULL constraint failed

I am just starting to learn about Django and I am running into an issue. I have a modelFormSet that is meant to add 3 choices to a question you create. I have no issue when I am not using the modelFormset and only adding one question but when I try to iterate through a modelsFormset and assign each choice to the question that was just created I get the following error:

NOT NULL constraint failed: polls_choice.question_id

I think it has something to do with the question_id not being passed to the choice model but I am not sure how to fix it. I have run fresh migrations and I don't think I can set blank or null to True since I need the choice and question to be related. Thank you in advance for your help!

Models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    assigned_to = models.ManyToManyField(User)
    def __str__(self):
        return self.question_text
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'

class Choice(models.Model):
    question = models.ForeignKey(Question)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    def __str__(self):
        return self.choice_text

Forms

class CreateQuestion(forms.ModelForm):
    class Meta:
        model = Question
        fields = ('question_text', 'assigned_to', 'pub_date',)


class AddChoices(forms.ModelForm):
    class Meta:
        model = Choice
        fields = ('choice_text',)

View

def create_question(request):
    choices_formset = modelformset_factory(Choice, form=AddChoices, fields=('choice_text',), extra=3)
    if request.method == 'POST':
        question_form = CreateQuestion(data=request.POST)
        choice_form = choices_formset(request.POST, request.FILES)
        if question_form.is_valid and choice_form.is_valid:
            question = question_form.save()
            for choice in choice_form:
                choice.question = question
                choice.save()
            return HttpResponseRedirect(reverse('polls:index'))
        else:
            return render(request, 'polls/createquestion.html', {'question_form': question_form,
                                                                 'choice_form': choice_form, })
    else:
        question_form = CreateQuestion()
        choice_form = choices_formset(queryset=Choice.objects.none(),)
        return render(request, 'polls/createquestion.html', {'question_form': question_form,
                                                             'choice_form': choice_form, })

When you loop through for choice in choice_form , each item is a form, so setting the question attribute doesn't work.

Instead, you should save with commit=False , set the question, then save the object to the db.

for form in choice_form:
    choice = form.save(commit=False)
    choice.question = question
    choice.save()

Problem is here:

            for choice in choice_form:
                choice.question = question
                choice.save()

You're iterating here over AddChoices forms, not over Choice objects. That mean, you're saving question as an attribute of form, not as attribute of model instance and that won't propagate into model instance.

To fix it you can try:

            for form in choice_form:
                choice = form.save(commit=False)
                choice.question = question
                choice.save()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM