教程民意调查应用程序的简单和逻辑扩展将在每页显示几个问题,并带有一个“提交”按钮。我有一个混合设计,它使用ModelForms来处理多场问题,但是单独渲染字段用于单场问题。所以标准的question_set页面由:
呈现{% load custom_tags %}
{% block question_set %}
<form action="{% url 'polls:answer' user.username %}" method="POST">
{% csrf_token %}
{% for question in page_question_list %}
<hr/>
{% if question.answer_type == "CH" %}
{% include "polls/Choice_Answer_form.html" %} {%endif%}
{% if question.answer_type == "SA" %}
{% include "polls/Short_Answer_form.html" %} {%endif%}
{% if question.answer_type == "LA" %}
{% include "polls/Long_Answer_form.html" %} {%endif%}
{% if question.answer_type == "E3" %}
{% include "polls/EJ_Answer_form.html" with form=forms|get_item:question%}
{%endif%}
{% if question.answer_type == "E4" %}
{% include "polls/EJ_Answer_form.html" with form=forms|get_item:question%}
{%endif%}
{% if question.answer_type == "BS" %}
{% include "polls/brainstorm_form.html" %}
{% endif %}
{% endfor %}
<br/>
<hr/>
<input type="submit" value="Submit" />
</form>
{% endblock %}
我有一种感觉,我错过了关于表格应该如何工作的基本信息。当您创建ModelForm对象并将其发送出去进行渲染时,它会知道它在模型中对应的实例(在我的例子中,问题编号和user_id)。当它从浏览器返回时,如果您已禁用,只读或隐藏那些(id,pk等)字段,则该信息将消失。您可以将该信息放在URL中,但只有在每页上处理单行数据时才可行。在文档中[examples] [1]高兴地展示了如何使用ModelForm(request = request,instance = instance),但我不知道如何设计它以使请求和实例保持同步。
我研究过的一些策略:
在formsets和use the 'prefix' to differentiate them中捆绑所需的表单。不确定问题编号关联是否可以保留用于渲染(怀疑它可以)或恢复,如果它仍然从POST数据中删除(怀疑它不能)。
修改渲染的字段名称以包含密钥信息(问题编号,用户)以防止它们在html命名空间中重叠,并且仅提交最后提交的值e.g. generate a new field for the form with the data in it to be rendered and presumably passed back或定义在构造函数中设置html_field_name的函数
使用表单'auto_id'(请参阅docs)字符串为每个字段赋予一个唯一的名称来编码问题编号 - 怀疑这应该是多余的,并且由一个表单集中的专业人员更好地处理,但请看我的第一个想法。
我可能想尝试最简单,最好的第一个;任何建议都感激不尽。
(我有更多的链接,但不允许以极少的状态发布它们)
答案 0 :(得分:0)
我发现从每个表单的'prefix'(但不是auto_id)字段加载和检索问题编号作为字符串“qNN#”可以工作(因为前缀应用于元素名称,auto_id适用于id,以及POST数据使用的名称)。我已将所有这些逻辑放在'views.py'
中捕获提交的表单的视图必须查看request.POST中的键,当它找到以q开头的键时,它会找出字段来自哪个问题并将请求传递给问题以创建来自请求+前缀的表单。
这意味着每次找到form_data时都会将request.POST发送到我的form_instantiator帮助函数,而不是将它们作为一组进行迭代。
不管怎样,我对Django感到内疚。