Reputation: 139
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, })
Upvotes: 1
Views: 1760
Reputation: 20569
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()
Upvotes: 1
Reputation: 309099
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()
Upvotes: 2