0

快速总结:如何确保 request.POST 中值的正确顺序?

我正在使用一个 HTML 表(使用 DataTables 增强以隐藏列等,唯一的效果是隐藏列不包含在对“提交”的调用中)并每行呈现一个变形表单。

由于变形不直接支持使用 form 属性的拆分表单,我手动插入form=my_desired_unique_id到所有相关元素中。<input>这对于像and之类的简单元素很有效<textarea>,这些值会显示在中request.POST.items()并且可以很好地验证。

不过,对于变形日期选择器来说,事情要复杂一些。form['datecolumn'].serialize会产生这样的东西: -

<input type="hidden" name="__start__" value="datecolumn:mapping"/>
<input type="date"
       name="date"
       value="2017-01-01"
       id="deformField6" class="  form-control hasDatepicker"/>
<input type="hidden" name="__end__" value="datecolumn:mapping"/>
<script type="text/javascript">
 deform.addCallback(
  'deformField6',
   function deform_cb(oid) {
     if (!Modernizr.inputtypes['date'] ||"date" != "date" || window.forceDateTimePolyfill){
       $('#' + oid).pickadate({"format": "yyyy-mm-dd", "selectMonths": true, "selectYears": true, "formatSubmit": "yyyy-mm-dd"});
     }
   }
 );
</script>

那里有 3 个输入(在渲染的 HTML 中添加了第四个隐藏的输入,名称为“date_submit”)。当用户选择新日期时,可见输入的值不会改变,但新的隐藏输入会改变。在提交时,该值以某种方式传递到主“日期”输入(一些我没有处理的 js)。

结果request.POST.items()包含来自日期输入的这三个元素:-

  1. ('__start__', 'datecolumn:mapping')
  2. ('date', '2017-02-24')(这是新选择的日期)
  3. ('__end__', 'datecolumn:mapping')

我的问题是这些值的顺序是不可靠的。在同一页面和表单上,多次单击提交将导致request.POST.items()(所有值,而不仅仅是与日期相关的值)中的值顺序不同。如果生成的顺序如上所示,则一切正常,但如果顺序不同(比如结束在开始之前,或者日期在两者之后或之前),那么我要么得到 ValueError 引发,要么验证失败。

我可以先遍历request.POST.items()并确保正确的安排,但我想要这种形式的两个日期选择器,我无法知道哪个date字段属于哪对__start____end__标记。

在将 POST 发送到我的视图代码之前,有什么方法可以控制 POST 中元素的顺序?

4

1 回答 1

0

我想出的技巧(将接受任何更好的答案!)涉及两个部分。

  1. 在我的模板中唯一地标记每个日期元素(我将所有日期元素命名为 *_date)。

  2. 使用模板重新生成适当的 POST 项目。

具体来说,对于第一步,我使用此函数生成序列化小部件:-

def serialize_with_formid(form, elem_name, formid):
    retval = form[elem_name].serialize()
    retval = retval.replace('<input type=', '<input form={} type='.format(formid))
    retval = retval.replace('<textarea', '<textarea form={}'.format(formid))
    if elem_name.endswith('date'):  # 'Mark' datepick elements appropriately
        retval = retval.replace('name="date"', 'name="{}"'.format(elem_name))
    return retval

form是创建的表单实例,elem_name以 datepicker 元素的“日期”结尾,并且formid对于页面上的每个表单都是唯一的(我的页面中有很多表单)。第 2 行和第 3 行在适当的地方插入formid,并if标记 datepicker 元素。

对于第 2 步,我首先从 中删除所有__start____end__元素request.POST,然后找到以request.POST结尾的元素date并使用它们将元素(以正确的顺序)附加到request.POST.

def fix_broken_POST(request):
    '''
    For some reason I'm getting POST elements out of order with retail rendered
    form-attribute reliant forms. This reorders the crucial elements (date-related)
    so that deform can then do validation etc.
    '''
    while True:
        try:  # Assumes same number of both
            request.POST.pop('__start__')
            request.POST.pop('__end__')
        except KeyError as e:
            break
    list_of_date_keys = [i for i in request.POST.keys() if i.endswith('date')]
    list_of_tuples = []
    for key in list_of_date_keys:
        value = request.POST.pop(key)
        list_of_tuples.append(('__start__', '{}:mapping'.format(key)))
        list_of_tuples.append(('date', value))
        list_of_tuples.append(('__end__', '{}:mapping'.format(key)))
    request.POST.extend(list_of_tuples)

同样,这显然是一个 hack/workaround,所以更多的东西......优雅将不胜感激。

于 2017-02-24T03:17:40.150 回答