在同一视图中使用多个表单

时间:2011-01-18 11:49:19

标签: python django

我正在尝试使用少量示例应用程序来学习django框架。目前,我正在制定反馈/调查申请。 它使用以下模型:

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()

基本上,调查将包含问题,他们的答案将保存在答案中。

现在我不明白的是如何创建一个表单,在调用视图时显示调查的所有问题。 我试图创建一个这样的表单

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()]

查看此内容就像

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)
        )

这样做的是,它会根据需要生成表单,但所有答案都会从最后一个答案字段中保存。 请帮帮我,使用formsets这会更容易吗,你能告诉我它如何更容易实现吗?感谢

3 个答案:

答案 0 :(得分:2)

原因可能是表单字段的名称发生冲突。

你可以解决这个问题,但是你已经看过Formsets Documentation了吗?

  

formset是在同一页面上处理多个表单的抽象层。

答案 1 :(得分:1)

您无法从请求对象获取,客户端www页面中有多少表单。
允许在html文档中使用多个表单 - 但唯一的区别是POST / GET数据仅包含提交表单中的字段。 因此,将所有输入数据放在一个表格中然后 最简单的解决方案是在模板中编写类似的内容

<form action="your_viw" method="post">
    {% for q in questions %}
        {{q.question}}<input name="q_{{q.id}}" type="text" />
    {% endfor %}
</form>

并在您的视图中

def show_questions(request, slug):
    survey = get_object_or_404(Survey.objects, slug=slug)
    context = {
        'survey':survey,
        'questions': survey.questions_set,
        }
    fields=[(int(name[2:]), val) for name, val in request.POST.items() if name.startswith('q_')]   # (question id, answer) list
    if fields:
         #validate fields
         # rest of work...
    return ...

很抱歉,如果有一些拼写错误的单词。

答案 2 :(得分:1)

prefix参数用于防止在重复使用相同的表单(FormSets使用它)或使用恰好具有冲突字段名称的表单时命名冲突问题 - 为每个Form提供唯一的{{} 1}},它将被添加到每个生成的字段名称之前。使用问题的ID是理想的:

prefix