Форма деформируемой в розницу формы (с использованием атрибута формы) - обработка даты ненадежна

Краткое резюме: Как обеспечить правильный порядок значений в request.POST?

Я использую таблицу HTML (дополненную с помощью DataTables, чтобы скрыть столбцы и т. Д., С единственным эффектом того, что скрытые столбцы не включаются в вызов 'submit') и отображаю одну форму деформации на строку.

Поскольку деформация напрямую не поддерживает разделенные формы с использованием атрибута формы, который я вставляю вручную 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 с именем date_submit). Значение видимого ввода не изменяется, когда пользователь выбирает новую дату, а новая скрытая -. При отправке, каким-то образом это значение передается на основной ввод 'date' (некоторые 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, прежде чем он будет отправлен в мой код просмотра?

1 ответ

Взлом, который я придумал (примет любые лучшие ответы, что это!) Состоит из двух частей.

  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 заканчивается "date" для элементов 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)

Опять же, это очевидно хак / обходной путь, так что что-то более... элегантное будет оценено.

Другие вопросы по тегам