【问题标题】:Django - Submitting form with multiple inputs for same fieldDjango - 为同一字段提交具有多个输入的表单
【发布时间】:2018-05-08 05:17:09
【问题描述】:

预警:我对 Django(以及一般的 Web 开发)非常陌生。

我正在使用 Django 托管一个基于 Web 的 UI,该 UI 将从一个简短的调查中获取用户输入,通过我用 Python 开发的一些分析来提供它,然后在 UI 中呈现这些分析的可视化输出.

我的调查包含 10 个问题,询问用户他们对特定主题的同意程度。

调查用户界面示例:

Example of UI input screen

对于 models.py,我有 2 个字段:问题和选择

class Question(models.Model):
    question_text = models.CharField(max_length=200)

    def __str__(self):
        return self.question_text

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text

我想让用户选择他们对所有 10 个问题的回答,然后单击提交以一次提交所有回答,但我在 Django 中如何处理这方面遇到了麻烦。

这是我正在使用的 html 表单,但是这段代码 sn-p 在每个问题之后放置一个“提交”按钮,并且一次只允许提交一个。

注意:下面的代码为每次迭代创建一个特定于问题的表单。

{% for question in latest_question_list %}
    <form action="{% url 'polls:vote' question.id %}" method="post">
    {% csrf_token %}
        <div class="row">
            <div class="col-topic">
                <label>{{ question.question_text }}</label>
            </div>
            {% for choice in question.choice_set.all %}
                <div class="col-select">
                    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
                    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
                </div>
            {% endfor %}
        </div>

    <input type="submit" value="Vote" />
    </form>
{% endfor %}

我对如何在一次提交中获取多个输入(全部用于问题/选择)并将其返回给 views.py

很感兴趣

编辑:添加 VIEWS.PY

目前,我的 views.py 脚本处理单个问题/选择对。一旦我弄清楚如何允许用户一次性提交所有 10 个问题/选择的表单,我将需要在 views.py 中反映这一点。这可能是问题的第 2 部分。首先,如何让用户通过一个“提交”按钮提交对所有 10 个问题的所有回复?其次,如何设置 views.py 一次接受多个值?

views.py

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        return render(request, 'polls/survey.html', {
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()

        return HttpResponseRedirect(reverse('polls:analysis'))

如果需要其他上下文,请告诉我。

提前致谢!

-C

【问题讨论】:

  • 您能告诉我们更多关于您当前如何在您的views.py 中获取表单数据的信息吗?
  • @PiyushDas,感谢您提请注意。我已更新说明以包含此信息。
  • 所以,您是说,在按下提交时,您只能得到一个问题/选择对,即使用户已经回答了每个问题。是这个问题吗?
  • 我可以让用户一次提交每个问题的回答,方法是为 10 个问题中的每一个问题创建一个单独的表单,并在每个问题旁边都有一个“提交”按钮10个问题。我想要做的是允许用户选择他们所有的答案(每个问题一个),然后单击一次提交以一次性提交他们的所有 10 个答案。

标签: python html django forms


【解决方案1】:

理想情况下,这应该使用 Django Forms 完成。 Django 表单有widgets 和RadioSelect 就是其中之一。您可以使用它来呈现您的表单并立即获得每个问题的答案。 但这需要对你目前做事的方式做出很大改变。

因此,您可以做的是,单击提交按钮,收集所有问题/选择对,并通过 POST 请求立即发送。

{% for question in latest_question_list %}
    <form>
        <div class="row">
            <div class="col-topic">
                <label>{{ question.question_text }}</label>
            </div>
            {% for choice in question.choice_set.all %}
                <div class="col-select">
                    <input type="radio" name="choice" value="{{ choice.id }}" />
                    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
                </div>
            {% endfor %}
        </div>
    </form>
{% endfor %}
<input id="submit-btn" type="submit" value="Vote" />

<script>
    $(document).on('click', '#submit-btn', function(event){
        var response_data = []
        var question_objs = $('.col-topic');
        var choice_objs = $('.col-select');

        for(i=0;i<question_objs.length;i++){
            var question_text = $(question_objs[i]).find('label').text();
            var choice_id = $(choice_objs[i]).find('input').val();
            var choice_text = $(choice_objs[i]).find('label').text();
            var question_choice = {
                "question_text": question_text,
                "choice_id": choice_id,
                "choice_text": choice_text
            }
            response_data.push(question_choice);
        }
        $.ajax({
            type: "POST",
            url: "url_to_your_view",
            data: response_data,
            success: function(response){
                alert("Success");
            }
        });
    });
</script>

这就是您的视图应该是什么样子。

def question_choice_view(request):
    if request.method == "POST":
        question_choice_data = request.POST['data']
        # further logic

现在,question_choice_data 是一个字典列表。列表中的每个dict都会有用户回复的question_text、choice_text和choice id。

【讨论】:

  • 啊,我从来没有尝试过使用 Django Forms。我会试试这个并回复你。我很欣赏你的回应。如果我成功了,会通知你。
【解决方案2】:

使用 getlist() 在你的意见中.py

if method=="POST":
    choices = request.POST.getlist('choice')

我觉得您应该将输入单选更改为复选框。 Radio 不允许多项选择,但 Checkbox 允许。 参考这里:https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.QueryDict.getlist

【讨论】:

  • 感谢您的回复。我的描述可能有点不清楚,但就我而言,每个问题只有 1 个回复。我希望在一个表单提交中提交 10 个问题和 10 个回复。在我上面描述的链接图像中,问题是粗体(即“堕胎是女性不受限制的权利”),响应/选择是单选按钮值。
【解决方案3】:

您只需要稍微不同地组织您的模板,以便在同一个form 中有多个问题。在 HTML 中,它会翻译成多个文本输入,然后在下面提交一个输入,所有这些都在一个表单中:

<form action="{% url 'polls:vote' question.id %}" method="post">
    {% for question in latest_question_list %}
    {% csrf_token %}
        <div class="row">
            <div class="col-topic">
                <label>{{ question.question_text }}</label>
            </div>
            {% for choice in question.choice_set.all %}
                <div class="col-select">
                    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
                    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
                </div>
            {% endfor %}
        </div>
    {% endfor %}
    <input type="submit" value="Vote" />
</form>

现在可以用了吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 2020-11-03
    • 1970-01-01
    相关资源
    最近更新 更多