Форма деформируемой в розницу формы (с использованием атрибута формы) - обработка даты ненадежна
Краткое резюме: Как обеспечить правильный порядок значений в 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()
содержит эти три элемента из даты ввода:
('__start__', 'datecolumn:mapping')
('date', '2017-02-24')
(это вновь выбранная дата)('__end__', 'datecolumn:mapping')
Моя проблема здесь в том, что порядок этих значений ненадежен. На одной и той же странице и в форме нажатие кнопки "Отправить" несколько раз приведет к различным порядкам значений в request.POST.items()
(все значения, а не только связанные с датой). Если результирующий порядок такой же, как указано выше, все работает нормально, но если порядок другой (скажем, конец - до начала или дата - после или до обоих), то я либо получаю значение ValueError, либо ошибка проверки.
Я мог бы перебрать request.POST.items()
сначала и обеспечить правильную договоренность, но я хочу двух сборщиков даты в этой форме, и я не могу знать, какие date
поле принадлежит какой паре __start__
а также __end__
маркеры.
Есть ли способ контролировать порядок элементов в POST, прежде чем он будет отправлен в мой код просмотра?
1 ответ
Взлом, который я придумал (примет любые лучшие ответы, что это!) Состоит из двух частей.
Пометить каждый элемент даты (я называю все мои элементы даты как *_date) уникально в моем шаблоне.
Используйте шаблон для повторного создания соответствующих элементов 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)
Опять же, это очевидно хак / обходной путь, так что что-то более... элегантное будет оценено.