I am trying to learn django framework with few sample applications. Currently, I am working on a feedback/survey application. It uses the following models:
class Survey(models.Model):
title = models.CharField(_(max_length=255)
slug = models.SlugField(_(max_length=255, unique=True)
description= models.TextField(blank=True)
class Question(models.Model):
survey = models.ForeignKey(Survey, related_name='questions')
question = models.TextField()
class Answer(models.Model):
question = models.ForeignKey(Question, related_name='answers')
answer = models.TextField()
Basically a survey will contain questions and their answers will be saved in the answer.
Now what I don't understand is how to create a form which will display all the questions of a survey when the view is called. I tried to create a form like this
class BaseAnswerForm(Form):
answer = None
def __init__(self, question,*args, **kwdargs):
self.question = question
#self.answer = None
super(BaseAnswerForm, self).__init__(*args, **kwdargs)
answer = self.fields['answer']
answer.label = question.question
def save(self, commit=True):
ans = self.answer
if ans is None:
ans = Answer()
ans.question = self.question
ans.answer = self.cleaned_data['answer']
if commit: ans.save()
return ans
class TextAnswerForm(BaseAnswerForm):
answer = CharField()
def forms_for_survey(survey, request):
if request.POST:
post = request.POST
else:
post = None
return [TextAnswerForm(q,data=post)
for q in survey.questions.all()]
view for this is like
def show_questions(request, slug):
survey = get_object_or_404(Survey.objects, slug=slug)
forms = forms_for_survey(survey, request)
context = {
'survey':survey,
'forms':forms,
}
if (request.POST and all(form.is_valid() for form in forms)):
for form in forms:
form.save()
return HttpResponseRedirect(reverse('show_surveys',))
return render_to_response(
'feedback/show_questions.html',
context,
context_instance = RequestContext(request)
)
What this does is that, it generates the form as I want, but all the answers are saved from the last answer field. Please help me out, will this be easier using formsets, Can you tell me how it can implemented easier. Thanks
The reason is probably that the names of the form fields clash.
You could work around that issue, but did you already have a look at the Formsets Documentation?
A formset is a layer of abstraction to working with multiple forms on the same page.
The prefix argument is there to prevent naming conflict issues when repeatedly using the same form (FormSets use it) or using forms which happen to have clashing field names - give each Form a unique prefix, which will be prepended to each generated field name. Using the Question's id would be ideal:
return [TextAnswerForm(q,data=post, prefix='q_%s' % q.pk)
for q in survey.questions.all()]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With