Django:Disabled Dropdown不会将信息发送回POST

Hou*_*man 12 python django

我在模型中有一个下拉列表,用户不应该更改所选的值.我发现a disabled确实做到了我需要的东西.然而,这有点奇怪:

表单打开(GET)时第一次选择该值,用户无法更改该值.这很棒:

在此输入图像描述

但是一旦出现验证错误unrelated field并且POST将用户返回到同一表单,之前的信息就会丢失.禁用的外键 - 下拉列表不再包含任何值,并且非常恼人.

在此输入图像描述

我做了一些研究并在stackoverflow上找到了一些东西,并且似乎在禁用了foreignkey-dropdown小部件时,根本没有发回任何数据.虽然可以覆盖验证,但不会为下拉字段抛出任何错误,因为这里第三个答案解释了.但是,如果任何其他不相关的字段抛出错误,则数据将丢失,因为禁用的下拉列表从未在第一时间向POST发送任何数据.

这是一个棘手的情况.

有没有办法将视图中的数据传递给request.POST?或者你的建议是什么?我可以使用a readonly而不是也可以使用disabled,但是用户可以更改下拉列表,这也很烦人.

有任何想法吗?非常感谢

编辑:

小修正:数据没有完全丢失.而是将选择错误地设置为初始虚拟值.

    <select id="id_form-0-deal_type" name="form-0-deal_type" disabled="disabled">
      <option selected="selected" value="">---------</option>
      <option value="1">deal 1</option>
      <option value="2">deal 2</option>
    </select>
Run Code Online (Sandbox Code Playgroud)

更新:

弗朗西斯的解决方案看起来非常有前景.所以我尝试了他的第二个建议,并在html中添加了一个隐藏的输入字段,并将正确的值传递给POST.

问题是现在如何进行.我试图像这样在formset的形式的querydict中添加缺少的条目(为了设置正确的下拉值)

formset.forms[0].data['form-0-deal_type'] = formset.forms[0].data['form-0-hiddenfield'] 
Run Code Online (Sandbox Code Playgroud)

但它说 This QueryDict instance is immutable

唯一的另一种方法是使用常规表单集将其设置为Initials.不幸的是我使用的是modelformsets,它不支持现有表单的首字母.

如果没有其他解决方案,我开始将我的modelformset重构为常规formset.仍然愿意接受...

最终更新+解决方案:

无需将modelformset重构为常规fomsets.事实上,我非常不鼓励这样做,因为它带来了其他问题.modelformsets为您处理所有事情并填补缺失的部分.

实际的问题是QueryDict是不可变的,但这可以通过复制它们轻松解决:

formset = deal_formset(request.POST, queryset=formset_query)        
if formset.is_valid():
  pass
else:
  new_post = request.POST.copy()
  deal_types = dict()
  for k,v in new_post.items():
     if k.startswith('hidden'):
        deal_types[k[7:]]= v
  for k,v in deal_types.iteritems():
     new_post[k] = v
  formset = deal_formset(new_post, queryset=formset_query)
Run Code Online (Sandbox Code Playgroud)

这加上弗朗西斯的解决方案:

{{ formset.management_form }}
  {% for fs in formset %}  
     {{ fs.id }} 
     <input type="hidden" name="hidden-{{ fs.prefix }}-deal_type" value="{{fs.deal_type.value}}" />
   {{fs.deal_type}}
{% endfor %}
{% endif %}
Run Code Online (Sandbox Code Playgroud)

只是创造奇迹...享受:)

Fra*_*llo 18

它不是django的东西,它是一个HTML的东西.表单不发送禁用的表单元素.

[元素]无法接收用户输入,也无法使用表单提交其值.

http://www.w3.org/TR/html401/interact/forms.html#h-17.12.1&http://www.w3schools.com/tags/att_input_disabled.asp

readonly如果它在文本/ textarea上 可以使用http://www.w3schools.com/tags/att_input_readonly.asp

你可以做的其他事情,是显示价值明文,并将其作为一个隐藏的领域提交....

{{ form.field_name.label_tag }}
{{ form.field_name.value }}
<input type="hidden" name="field_name" value="{{form.field_name.value}}" />
Run Code Online (Sandbox Code Playgroud)

它不是很优雅,但它可以让你到那里.

您还可以更进一步,编写一些查找已禁用元素的JS,然后添加一个带有该元素名称和值的输入.

一些示例JQuery:

//Untested, but you get the gist
$(':disabled').each(
    function()
    {
        $(this).after('<input type="hidden" name="' + $(this).attr('name') + '" value="' + $(this).val() + '" />');
    }
);
Run Code Online (Sandbox Code Playgroud)