Comment faire un formset dynamique à Django?
, Voici la façon dont je suis en train de faire:
{{ formset.management_form }}
<table>
{% for form in formset.forms %}
{{ form }}
{% endfor %}
</table>
<a href="javascript:void(0)" id="add_form">Add Form</a>
et voici le 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);
});
ce qui me dérange particulièrement, c'est que j'ai dû écrire moi-même cette étiquette de modèle escapejs
. Il enlève juste toutes les nouvelles lignes et échappe à toutes les guillemets simples de sorte qu'il ne gâche pas ma corde. Mais qu'est-ce que les fabricants de Django attendaient de nous dans cette situation? Et pourquoi ont-ils cette TOTAL_FORMS
champ caché, alors qu'ils pourraient juste un tableau comme <input name="my_form_field[0]" />
et puis compté sa longueur à la place?
5 réponses
il y a quelques endroits à Django où" la raison pour laquelle " est parce que c'est comme ça que ça a été implémenté pour L'application Admin Django, et je crois que c'est l'un d'eux. Ainsi, la réponse est qu'ils s'attendent à ce que vous implémentiez votre propre javascript.
voir cette question ajout dynamique d'un formulaire... pour plus d'idées javascript.
Il y a aussi deux enfichable applications disponibles, django-dynamique-formset et django-dinamyc-forme que je n'avais pas vu jusqu'à présent en regardant vers le haut de la première.
Cette question est un peu vieux, mais il m'a fallu un certain temps pour comprendre cela.
je suggère de rendre formset.empty_form dans votre template comme un champ caché, et référencement de ce champ dans votre javascript.
voici un exemple de formset dynamique compliqué du site admin django: (mais notez qu'il n'a pas été mis à jour pour utiliser empty_form....)
[js] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/inlines.js
[modèle html] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html
c'est parce que formset ont été créés pour fonctionner sans javascript , en utilisant seulement le flux HTTP habituel.
Django est un agnostique javascript.
si vous voulez ajouter du javascript au mix, vous pouvez utiliser le dédié au plugin jquery .
dans mon cas. j'ai utilisé le plugin django-dynamic-formset ( https://code.google.com/p/django-dynamic-formset/wiki/Usage )
et a modifié l'option" ajouté " et a bien fonctionné.
$('#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);
},
cette expression régulière remplacer la chaîne [préfixe]- préfixe "1519120920 par les pairs" ' - '
n'est peut-être pas la meilleure solution, mais ça a marché.
dans certains cas, il est possible d'utiliser XSS avec formset.empty_form
comme chaîne de caractères, en remplaçant '__prefix__'
par "formset form index". Mon application branchée convertit formset.empty_form
en Knockout.js template qui est ensuite cloné via Knockout personnalisé.js liaisons. Aussi Knock-Out.js recalcule automatiquement les index d'id de champ de formulaire, lorsque le nouveau formset est supprimé dynamiquement avant que le formulaire entier avec les formetsinline n'ait été soumis. Voici la documentation:
K. O.js binding empêche également XSS lors du chargement des champs personnalisés avec Javascript en ligne.