【问题标题】:Creating Django form questionnaire with radio buttons使用单选按钮创建 Django 表单问卷
【发布时间】:2019-01-27 01:55:03
【问题描述】:

我正在尝试在我的 django 应用程序中实施一项调查。目前我通过手动绘制表单结构的 HTML 来实现它,如下所示:

      <!-- Question 1-->
  <form method="post" action="{% url 'piuserform' %}">
    {% csrf_token %}
    <div class="mx-auto">
      <h3 class="mb-4">At the time of the accident, the injured party was: </h3>
      <label class="radcontainer">The driver of an automobile.
            <input type="radio" name="question1" value="The driver of an automobile">
            <span class="checkmark"></span>
          </label>
      <label class="radcontainer">The passenger of an automobile.
            <input type="radio" name="question1" value="The passenger of an automobile">
            <span class="checkmark"></span>
          </label>
      <label class="radcontainer">A pedestrian.
            <input type="radio" name="question1" value="A pedestrian">
            <span class="checkmark"></span>
          </label>
    </div>
    <!-- /Question 1 -->


    <!-- question 3-->
    <div class="mx-auto pt-5">
      <h3 class="mb-4">How many vehicles were involved in the accident?</h3>
      <label class="radcontainer">One
            <input type="radio" name="question3" value="One">
            <span class="checkmark"></span>
          </label>
      <label class="radcontainer">Two
            <input type="radio" name="question3" value="Two">
            <span class="checkmark"></span>
          </label>
      <label class="radcontainer">Three
            <input type="radio" name="question3" value="Three">
            <span class="checkmark"></span>
          </label>
      <label class="radcontainer">Four or more
            <input type="radio" name="question3" value="Four or more">
            <span class="checkmark"></span>
          </label>
    </div>
    <!-- /Question 3 -->

现在我尝试使用 Django forms api 来实现这种效果,但它只会呈现最后一个问题。问卷都是单选按钮,答案字段变化很大。有没有办法自动化这个,所以我可以通过 modelForm 或 Formsetfactory 使用 {{form}} 渲染?我查看了许多文档,但没有一个对我的问题真的很清楚,当我尝试像我说的那样实现表单 api 时,它只会呈现一个问题。非常感谢您的帮助

编辑:

当我尝试实现表单 API 时,我使用了这种方法:

forms.py

blah_choices = [("1", "first"), ("2", "second")]
blah_choices2 = [("3", "third"), ("4", "four")]

class testRadioQuestions(forms.Form):
    q1 = forms.ChoiceField(label="Blah blah blah form question",
                           choices=(blah_choices),
                           widget=forms.RadioSelect()),
    q2 = forms.ChoiceField(label="blah blah some more form question",
                           choices=(blah_choices2),
                           widget=forms.RadioSelect())

查看

def other_questionnaire(request):
     if request.method == "POST":
         print(request.body)
     return render(request, 'website/otherQuestions.html', {'form': form})

【问题讨论】:

  • 您使用的是模型吗?展示您的视图和表单。
  • 我尝试使用 forms.Form。我似乎无法通过至少两个单选按钮得到一组一致的问题。

标签: django forms api radio


【解决方案1】:

这看起来工作量很大。我认为问题可能是您的视图上下文只有最后一种形式。您将需要创建一个表单列表或字典。您还需要使用“prefix”来区分他们的“id”。

我为此制定了一个解决方案,但(我想像你一样)我有一种挥之不去的感觉,我错过了“表单”api 中的一些重要内容。

我的解决方案是手动为每个表单分配一个前缀,这样我就可以将它从 POST 解压到正确的表单子类中。我不会发布所有不同的部分,但这里有一个草图:

# forms.py
AnswerMap = { question_answer_type1 : FormClass1, etc etc }
def form_get(question, instance=None):
    answerform = AnswerMap[question.answer_type](instance=instance) # not sure this works, may need to handle two cases separately.
    return answerform 

def form_post(question, data, instance=None):
    answerform = AnswerMap[question.answer_type](data=data, instance=instance)
    if answerform.is_valid():
        return answerform
    else:
        pass  # handle error, I guess.

下一部分是视图。我在这里通过 request.POST 的方式似乎非常低效,因为我经历了两次 - 第一次收集前缀并找出存在哪些问题,第二次(在单一理解中)收集每个前缀的数据。但我还没有想出更好的办法。

# views.py
class page_view(View):
    def get(self, page_no):
        forms = {}
        questions = Question.objects.filter(page=page_no)
        for question in questions:
            forms[question] = get_form_for_question(question, prefix=('q'+question.pk))
        self.context['forms'] = forms
        return render(request, template, context)

     def post(self, page_no)
         prefixes = []
         self.form_items = {}
         for key, value in request.POST.items():
             if key.startswith("q"):
                 q_number = re.search(r'q(\d+)#', key)
                 pk_q = int(q_number.group(1))  # the digits are the question primary key
                 prefix = 'q' + str(pk_q)
                 if prefix not in prefixes:
                     prefix.append(prefix)
                     question = Question.objects.get(pk=pk_q)
                     self.form_items[prefix] = {key: val for key,val in request.POST.items() if prefix in key}  # collects data for form; add any data that you don't render but will need in the database somewhere here - e.g. username or timestamp
                     form = form_post(value=self.form_items[prefix], question=question)
                     if form.is_valid():
                         form.save()
         return HttpRedirectResponse('as appropriate')

添加自定义模板标签以解压模板中的表单:

# custom_tags.py
@register.filter
def get_item(dictionary, key):    
    return dictionary.get(key)

在模板中,提取所需的表单,如下所示:

{% load 'custom_tags' %}
{% for question in page_question_set %}
     {{question}}
     {{ forms|get_item:question }}
{% endfor %}

我希望你觉得这很有用。我不认为这是一个糟糕的解决方法,但我仍然担心我正在解决框架实际上可以处理的问题。

【讨论】:

【解决方案2】:

只需删除每个已定义字段末尾的 (逗号),这应该可以工作

forms.py

from django import forms

    blah_choices = [("1", "first"), ("2", "second")]
    blah_choices2 = [("3", "third"), ("4", "four")]

    class TestRadioQuestions(forms.Form):
        email = forms.EmailField()
        q1 = forms.ChoiceField(label="Blah blah blah form question",choices=(blah_choices),widget=forms.RadioSelect())
        q2 = forms.ChoiceField(label="blah blah some form question",choices=(blah_choices2),widget=forms.RadioSelect())

views.py

def testRadioQuestions(request):
    if request.method == 'POST':
        form = TestRadioQuestions(request.POST)

        if form.is_valid():
            return HttpResponseRedirect('../../url_name')


    else:
        form = TestRadioQuestions()

    return render(request, 'template_url', {'form' : form })    

【讨论】:

    猜你喜欢
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 2012-02-17
    相关资源
    最近更新 更多