Issue
I am trying to create a number of surveys in Django and put them in a survey index page. I have run into an issue: Up until now, all of my surveys had questions which had the same set of answer choices, so in my Django models I linked the answers only to the survey because it was the easiest for me and it was working. Now I have to add a new survey where each question has a different set of answers choices (if you are curious, this is the survey: https://www.fresno.ucsf.edu/pediatrics/downloads/edinburghscale.pdf). My problem is that for this new survey I am now getting every possible answer choice in the whole survey for each question.
How can I link the answer choices to the question so that I will only see the choices for the corresponding question? Yes, I have read the Django polls tutorial and have tried requesting the question_id, but then I got an error along the lines of "missing question_id" so I went back to my original code. I think the right approach would be to link the answer choices to both the question and the survey, but not sure.
Here is my model:
class Questionnaire(models.Model):
name = models.CharField(max_length=255)
text = models.CharField(max_length=200)
# def get_absolute_url(self):
# return reverse('questionnaire-detail', args=[str(self.id)])
def __str__(self):
return self.name
class Question(models.Model):
text = models.CharField(max_length=200)
questionnaire = models.ForeignKey(Questionnaire, on_delete=models.CASCADE, related_name='questions')
def __str__(self):
return self.text
class Answer(models.Model):
question = models.ForeignKey(Question, models.SET_NULL, blank=True, null=True, related_name='answerlist')
questionnaire = models.ForeignKey(Questionnaire, on_delete=models.CASCADE, related_name='answers', default='')
text = models.CharField(max_length=200)
image = models.CharField(null=True, max_length=20)
image_location = models.CharField(null=True, max_length=20)
def __str__(self):
return self.text
Here is my views:
ResponseFormSet = modelformset_factory(Response, form=ResponseForm, extra=0)
if request.method == 'POST':
formset = ResponseFormSet(request.POST or None, request.FILES, form_kwargs={'user': request.user})
if formset.is_valid():
print("Formset is valid")
formset.save()
return HttpResponseRedirect(reverse ('questionnaires:questionnaire_index'))
else:
print("Formset is NOT valid")
print(formset.errors)
print(formset.non_form_errors())
questionnaire = Questionnaire.objects.get(id=questionnaire_id)
questions = Question.objects.filter(questionnaire_id=questionnaire_id)
answers = Answer.objects.filter(questionnaire_id=questionnaire_id)
return render(request, 'questionnaires/questionnaire_lec.html', {
'questions': questions,
'answers': answers,
'questionnaire': questionnaire,
})
And my HTML:
<form method="post" action="{{ request.url }}">
{% csrf_token %}
<legend><h2>{{ questionnaire.text }}</h2></legend>
<br>
{% for question in questions %}
<h3>{{question.text}}</h3>
<label hidden="" for="id_form-{{ forloop.counter0 }}-question">Question:</label>
<select hidden="" name="form-{{ forloop.counter0 }}-question" id="id_form-{{ forloop.counter0 }}-question">
<option value="{{question.id}}" selected="">{{question.text}}</option>
</select>
<!-- <label for="id_form-{{ forloop.counter0 }}-answer">Answer:</label> -->
{% for answer in answers %}
<label for="id_form-{{ forloop.counter0 }}-answer">
<input type="radio" name="form-{{ forloop.parentloop.counter0 }}-answer" id="id_form-{{ forloop.counter0 }}-answer" value="{{answer.id}}">
{{answer.text}}
</label> <br>
{% endfor %}
<input type="hidden" name="form-{{ forloop.counter0 }}-id" value="{{ forloop.counter }}" id="id_form-{{ forloop.counter0 }}-id">
<input type="hidden" name="form-TOTAL_FORMS" value="{{questions|length}}" id="id_form-TOTAL_FORMS" />
<input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS" />
<input type="hidden" name="form-MAX_NUM_FORMS" value="{{questions|length}}" id="id_form-MAX_NUM_FORMS" />
{% endfor %}
<br />
<br />
<input type="submit" value="Submit">
</form>
{% endif %}
{% endblock %}
Thank you in advance for any help!
Solution
You should use:
{% for answer in question.answerlist.all %} … {% endfor %}
There is no need to pass a QuerySet
of Answer
s to the template.
Answered By – Willem Van Onsem
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0