零售渲染变形表格(使用表格属性) - 日期处理不可靠

时间:2017-02-23 04:18:52

标签: python http-post pyramid deform

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

我正在使用HTML表格(使用DataTables进行扩充以隐藏列等,唯一的效果就是隐藏列未包含在“提交”的调用中)并呈现一个每行变形。

在变形does not directly support split forms using the form attribute时,我手动将form=my_desired_unique_id插入所有相关元素。这适用于<input><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中添加了名称&#39; date_submit&#39;)。当用户选择新日期时,可见输入的值不会改变,但新隐藏的日期会发生。在提交时,不知何故将该值传递给主要日期&#39;输入(我没有处理过的一些js)。

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

  1. ('__start__', 'datecolumn:mapping')
  2. ('date', '2017-02-24')(这是新选择的日期)
  3. ('__end__', 'datecolumn:mapping')
  4. 我的问题是这些值的顺序不可靠。在同一页面和表单上,多次单击提交将导致request.POST.items()中的不同值顺序(所有值,而不仅仅是与日期相关的值)。如果结果顺序如上所述,事情就可以了,但如果顺序不同(比如结束是在开始之前,或者日期是在两者之前或之前),那么我会得到一个ValueError引发或验证失败。

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

    在将POST发送到我的视图代码之前,有没有办法控制POST中元素的顺序?

1 个答案:

答案 0 :(得分:0)

我提出的黑客攻击(会接受任何更好的答案!)涉及两个部分。

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

  2. 使用模板重新生成相应的POST项目。

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

    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以&#39; date&#39;结尾。对于datepicker元素,formid对于页面上的每个表单都是唯一的(我的页面中有很多表单)。第2行和第3行在适当的位置插入formidif标记为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)
    

    再次,这显然是一个黑客/解决方法,所以更多的东西...优雅将不胜感激。