2010-03-01 7 views
18

est ici la façon dont je le fais:Comment créer un formset dynamique dans Django?

{{ 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 la 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 plus particulièrement est que je devais écrire moi-même tag modèle escapejs. Il supprime juste toutes les nouvelles lignes et échappe à toutes les guillemets simples afin qu'il ne gâche pas ma chaîne. Mais qu'est-ce que les fabricants de Django attendaient exactement de nous dans cette situation? Et pourquoi ont-ils ce champ caché TOTAL_FORMS, alors qu'ils auraient pu simplement utiliser un tableau comme <input name="my_form_field[0]" /> et ensuite compté sa longueur à la place?

+1

Mais pourquoi mélangez-vous le modèle django et le javascript? – Prashanth

+0

Pour que je puisse le traiter. Sinon, je dois aussi écrire complètement la gestion des formulaires personnalisés dans la vue. Et Django semble encourager cette méthode, c'est * pourquoi * ils ont fourni ce 'empty_form' avec' __prefix__' pour que vous puissiez le remplacer, supposément. – mpen

+1

J'aime l'utilisation de '.empty_form' - agréable et court. Merci! –

Répondre

5

Il y a quelques endroits dans Django où "la raison" est parce que c'est ainsi que cela a été implémenté pour l'application d'administration Django, et je crois que c'est l'un d'entre eux. Ainsi, la réponse est qu'ils s'attendent à ce que vous implémentez votre propre javascript.

Voir cette question SO Dynamically adding a form... pour plus d'idées javascript.

Il y a aussi deux applications enfichables disponibles, django-dynamic-formset et django-dinamyc-form que je n'avais pas vues jusqu'à présent en cherchant la première.

+1

Écrire mon propre JS n'est pas vraiment un problème ... Je suis simplement curieux de savoir pourquoi ils nous ont donné seulement la moitié des outils dont nous avons besoin ... ils disent que la forme empty_form peut être utilisé pour cela, mais il imprime avec des sauts de ligne et ce qui n'est pas très convivial pour travailler avec JS, à moins que je ne comprenne quelque chose. Je pense que j'aime mieux ma méthode de formset dynamique ... Je suppose qu'elle met moins de pression sur le client, et nécessite moins de code :) Eh bien ... je suppose que je suis juste en train de cogner, mais je suis encore vraiment en désaccord avec beaucoup des décisions de conception de Django. – mpen

+0

Eh bien Django décision de conception correcte est de rester JS-cadre neutre. L'admin est une application contrib et ne fait donc techniquement pas partie du noyau de Django, bien que certaines fonctionnalités telles que formsets (apparemment) proviennent du travail sur l'admin et, bien que je pense que l'admin est une bonne application, elle souffre probablement de l'absence d'un grand design. –

+3

Formsets sont une énorme douleur dans le cul si vous voulez faire quelque chose avec ajax ou ajouter dynamiquement de nouveaux objets. De loin le plus gros problème avec Django en essayant de concevoir une application de type Web 2.0. Nous avons presque basculé dans un framework Java après avoir investi 6 mois dans Django pour cette même raison, mais nous avons décidé que nous avions passé trop de temps. –

4

Cette question est un peu ancienne, mais il m'a fallu du temps pour la comprendre.

Je suggère de rendre formset.empty_form dans votre modèle comme un champ caché, et de référencer ce champ dans votre javascript.

Voici un exemple formset dynamique compliquée du site d'administration 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

[template html ] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html

+0

J'ai récemment (il y a quelques heures) refait ça ... c'est vraiment désagréable de travailler avec .. pour essayer d'ajouter et supprimer des formulaires, et mettre à jour tous les ID dispersés, et s'assurer qu'il y a au moins un formulaire, et valider les tous correctement ... combinez cela avec ajax/cascading/contingent sélectionnez les baisses et cela devient un cauchemar miniature. – mpen

+0

Avez-vous travaillé sur l'exemple de django inlines.js? Je l'ai modifié pour mon site (je voulais ajouter les boutons dans une liste séparée). Était pas trivial (je suis nouveau à js, il a donc fallu un certain temps), mais je pense que j'ai réussi à contenir la plupart de la logique dans un seul script indépendant. – bsk

1

C'est parce que formset ont été créés pour travailler sans javascript, en utilisant uniquement le flux de travail habituel HTTP.

Django est compatible avec javascript.

Si vous souhaitez ajouter du javascript au mélange, vous pouvez utiliser le dedicated jquery plugin.

+1

Souhaite que je pourrais voir une démo, mais merci. Django est conçu pour fonctionner sans JavaScript, mais il semble qu'il y ait des crochets mineurs pour compiler JavaScript sur ....Je souhaite juste qu'ils l'aient pris plus loin, parce que c'est douloureux. – mpen

+0

@Mark: En fait il y a une démo :-) Téléchargez le projet sur http://code.google.com/p/django-dynamic-formset/ il inclut une démo de django. –

+0

Ce n'est pas ce que je voulais dire par une démo. Je voulais dire sans avoir à le télécharger ("live demo"?). Il y a des millions de projets et de programmes ... les gens aiment savoir ce qu'ils obtiennent avant d'investir dans le temps et les efforts, de télécharger et d'extraire des choses et/ou d'installer/compiler. Quoi qu'il en soit, puisque vous l'avez * recommandé * et que ce n'est pas un hasard, je vais y jeter un coup d'œil ... (si c'est une bibliothèque si merveilleuse, on peut s'attendre à ce qu'elle soit utilisée quelque part pourrait simplement lier à ...) – mpen

1

dans mon cas. J'ai utilisé le plugin django-dynamic-formset (https://code.google.com/p/django-dynamic-formset/wiki/Usage)

et 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 [prefix] - préfixe pair '-'

est peut-être pas la meilleure solution, mais elle a travaillé.

1

Il existe des cas de XSS possible lors de l'utilisation de formset.empty_form en tant que chaîne, en remplaçant '__prefix__' par un index de formulaire de formulaire réel. Mon application enfichable convertit formset.empty_form en modèle Knockout.js qui est ensuite cloné via des liaisons Knockout.js personnalisées. En outre, Knockout.js recalcule automatiquement les index d'ID de champ de formulaire, lorsque le formulaire formset nouvellement ajouté est supprimé dynamiquement avant que le formulaire entier avec les formulaires en ligne ne soit soumis. Voici la documentation:

https://django-jinja-knockout.readthedocs.org/en/latest/forms.html#dynamically-adding-new-related-formset-forms

Knockout.js de liaison empêche également XSS lors du chargement des champs personnalisés avec ligne Javascript.

Questions connexes