Hi,
there seems to be a very subtle but NASTY bug that causes domande to save wrong answers on choice questions. I'm sorry I currently don't have time for a full pull request, but this should provide enough information to fix it!
Description of the bug
In forms.py, we take the IDs of choice answers that were selected by the user. Then we search for the corresponding choice objects and add them to the choiceanswer. The code looks like this:
real_answer = self.cleaned_data.get('answer')
...
choices = Choice.objects.filter(id__in=real_answer)
The goal here is to take the ID of all selected answers as strings and get the corresponding choice objects. But there's a problem: real_answer is a list if the question is multiple choice. But if it's a single choice question (radio buttons), then it's a string! That means that the query Choice.objects.filter(id__in=real_answer)
goes awry and does a search for IDs containing the real string ID!
This is especially bad, because it will only show if you have more than 9 choice objects. Example: A choice question is answered with real_answer "22". The query looks for any choice where the ID contains one of the chars in "22", for example Choice(id=2).
FIX
We need to make sure that real_answer is always a list, so the following should suffice but still needs to be tested!
Note the "elif": If real_answer is empty, we can't make it a list since that would foil the lookup again.
from survey.models import ChoiceAnswer, Choice
real_answer = self.cleaned_data.get('answer')
if not real_answer:
if self.fields['answer'].required:
raise forms.ValidationError, 'Required'
return
elif not isinstance(real_answer, list):
real_answer = [real_answer]
choices = Choice.objects.filter(id__in=real_answer)
PS: Here's another potential gotcha: We can't use real_answer = list(real_answer)
because that would split the string into a list!
Anyway, hope that helps!