Как сделать динамический набор форм в Django?
Вот как я это делаю:
{{ formset.management_form }}
<table>
{% for form in formset.forms %}
{{ form }}
{% endfor %}
</table>
<a href="javascript:void(0)" id="add_form">Add Form</a>
И здесь JS:
var form_count = {{formset.total_form_count}};
$('#add_form').click(function() {
form_count++;
var form = '{{formset.empty_form|escapejs}}'.replace(/__prefix__/g, form_count);
$('#forms').append(form)
$('#id_form-TOTAL_FORMS').val(form_count);
});
Что конкретно меня беспокоит, так это то, что мне пришлось написать этот тег escapejs
. Он просто убирает все новые строки и избегает каких-либо одиночных кавычек, чтобы он не испортил мою строку. Но что именно ожидали от разработчиков Django в этой ситуации? И почему у них есть это скрытое поле TOTAL_FORMS
, когда они могли бы просто использовать массив вроде <input name="my_form_field[0]" />
, а затем подсчитали его длину?
Ответы
Ответ 1
В Django есть несколько мест, где "причина" - это то, как это было реализовано для приложения администратора Django, и я считаю, что это один из них. Таким образом, ответ заключается в том, что они ожидают, что вы реализуете свой собственный javascript.
См. этот вопрос SO Динамическое добавление формы... для еще нескольких идей javascript.
Доступны также два подключаемых приложения, django-dynamic-formset и django-dinamyc-form, который я не видел до этого момента, когда смотрел первый.
Ответ 2
Этот вопрос немного устарел, но мне понадобилось время, чтобы понять это.
Я предлагаю визуализировать formet.empty_form в вашем шаблоне как скрытое поле и ссылаться на это поле в вашем javascript.
Здесь приведен пример сложного динамического набора форм с сайта администратора django:
(но обратите внимание, что он не был обновлен для использования empty_form....)
[JS]
http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/inlines.js
[шаблон html]
http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html
Ответ 3
Это потому, что formet был создан для работы без javascript, используя только обычный рабочий процесс HTTP.
Django является агностиком javascript.
Если вы хотите добавить javascript в микс, вы можете использовать выделенный плагин jquery.
Ответ 4
в моем случае. я использовал плагин django-dynamic-formset (https://code.google.com/p/django-dynamic-formset/wiki/Usage)
и изменил опцию "добавлено" и работал хорошо.
$('#formset-table tbody tr').formset({
prefix: '{{ formset.prefix }}',
formCssClass: '{{ formset.prefix }}-inlineformset',
added: function(obj_tr){
var form = $(obj_tr).html().replace(/\-(\w+)\-(\w+)(fix__)\-/g, '-');
$(obj_tr).html(form);
},
это регулярное выражение заменяет строку [префикс] - префикс peer '-'
возможно, не лучшее решение, но работало.
Ответ 5
Есть некоторые случаи возможного XSS при использовании formset.empty_form
в качестве строки, заменяя '__prefix__'
на фактический индекс формы формы. Мое подключаемое приложение преобразует formset.empty_form
в шаблон Knockout.js, который затем клонируется через пользовательские привязки Knockout.js. Кроме того, Knockout.js автоматически пересчитывает индексы идентификатора поля формы, когда новая форма формы формы динамически удаляется до того, как была отправлена вся форма с inlineformsets. Вот документация:
https://django-jinja-knockout.readthedocs.org/en/latest/forms.html#dynamically-adding-new-related-formset-forms
Связывание Knockout.js также предотвращает XSS при загрузке настраиваемых полей встроенным Javascript.