2010-03-01 13 views
18

Hier ist die Art, wie ich es tue:Wie würden Sie in Django ein dynamisches Formset erstellen?

{{ formset.management_form }} 
<table> 
    {% for form in formset.forms %} 
     {{ form }} 
    {% endfor %} 
</table> 
<a href="javascript:void(0)" id="add_form">Add Form</a> 

Und hier ist die 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); 
}); 

Was mich speziell, dass ich das escapejs Vorlage mich Tag schreiben musste stört ist. Es entfernt nur alle Zeilenumbrüche und es werden alle einfachen Anführungszeichen entfernt, so dass es meine Zeichenfolge nicht durcheinanderbringt. Aber was genau haben die Django-Macher von uns in dieser Situation erwartet? Und warum haben sie dieses versteckte Feld TOTAL_FORMS, wenn sie nur ein Array wie <input name="my_form_field[0]" /> hätten verwenden können und dann stattdessen ihre Länge gezählt hätten?

+1

Aber warum mischen Sie Django Vorlage und Javascript? – Prashanth

+0

Damit ich es verarbeiten kann. Ansonsten muss ich in der Ansicht auch komplett benutzerdefinierte Formularbearbeitung schreiben. Und Django scheint diese Methode zu unterstützen, das ist der Grund, warum sie diese "leere_Form" mit "__prefix__" versehen haben, so dass Sie sie angeblich ersetzen könnten. – mpen

+1

Ich mag die Verwendung von '.empty_form' - nett und kurz. Vielen Dank! –

Antwort

5

Es gibt ein paar Orte in Django, wo "der Grund warum" ist, weil es so für die Django Admin App implementiert wurde, und ich glaube, das ist einer von ihnen. Daher die Antwort ist, dass sie erwarten, dass Sie Ihr eigenes Javascript implementieren.

Sieh diese SO Frage Dynamically adding a form... für einige mehr Javascript Ideen.

Es sind auch zwei Pluggable-Apps verfügbar, django-dynamic-formset und django-dinamyc-form, die ich bis jetzt nicht gesehen habe, als ich die erste nachgeschlagen habe.

+1

Das Schreiben meiner eigenen JS ist nicht wirklich ein Problem ... Ich bin nur neugierig, warum sie uns nur die Hälfte der Werkzeuge gegeben haben, die wir brauchen .... sie sagen, die 'leere_Form' kann sein dafür verwendet, aber es druckt mit Zeilenumbrüchen und solche, die nicht sehr freundlich zu arbeiten ist, wenn es versucht, es in JS stopfen, es sei denn, ich missverstand etwas. Ich denke, dass ich meine Methode des dynamischen Formsets besser finde ... Ich vermute, dass es den Kunden weniger belastet und weniger Code erfordert :) Naja ... Ich schätze, ich bin nur pingelig, aber ich stimme immer noch nicht mit viel überein von Djangos Designentscheidungen. – mpen

+0

Nun Django richtige Design-Entscheidung ist JS-Framework neutral zu bleiben. Der Admin ist eine Contrib-App und gehört somit technisch nicht zum Django-Kern, obwohl einige Funktionen wie Formsets (anscheinend) von der Arbeit am Admin stammen und obwohl ich denke, dass der Admin eine gute App ist, leidet er wahrscheinlich etwas darunter aus Mangel an einem großen Design. –

+3

Formsets sind ein großer Schmerz im Hintern, wenn Sie etwas mit Ajax machen oder dynamisch neue Objekte hinzufügen möchten. Mit Abstand das größte Problem mit Django beim Versuch, eine Web 2.0-App zu entwickeln. Wir sind fast auf ein Java-Framework umgestiegen, nachdem wir aus genau diesem Grund 6 Monate in Django investiert hatten, entschieden aber, dass wir zu viel Zeit verbracht hatten. –

4

Diese Frage ist ein bisschen alt, aber es hat eine Weile gedauert, um das herauszufinden.

Ich empfehle formset.empty_form in Ihrer Vorlage als ein verstecktes Feld zu rendern und dieses Feld in Ihrem Javascript zu referenzieren.

Hier ist ein kompliziertes dynamisches formset Beispiel aus der django Admin-Seite: (aber beachten Sie, dass es nicht empty_form verwenden aktualisiert ....)

[js] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/inlines.js

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

+0

Ich vor kurzem (vor ein paar Stunden tatsächlich) redid dies ... es ist wirklich böse mit zu arbeiten .. zu versuchen und fügen Sie Formulare, und aktualisieren Sie alle verstreuten IDs, und stellen Sie sicher, es gibt mindestens ein Formular, und zu validieren sie alle richtig ... kombinieren Sie das mit Ajax/Cascading/Contingent wählen Sie Drop-Downs und es wird zu einem Miniatur-Albtraum. – mpen

+0

Haben Sie am Beispiel django inlines.js gearbeitet? Ich habe es für meine Website geändert (wollte die Hinzufügen-Schaltflächen in einer separaten Liste). War nicht trivial (ich bin neu in js, also hat es eine Weile gedauert), aber ich denke, dass ich es geschafft habe, den Großteil der Logik in einem einzigen unabhängigen Skript zu speichern. – bsk

1

Es ist, weil formset erstellt wurden ohne Javascript zu arbeiten, nur die üblichen HTTP-Workflow.

Django ist Javascript Agnostiker. Wenn Sie der Mischung etwas Javascript hinzufügen möchten, können Sie die dedicated jquery plugin verwenden.

+1

Ich wünschte, ich könnte eine Demo sehen, aber danke. Django ist entworfen, um ohne JavaScript zu arbeiten, ja, aber es scheint einige kleinere Hooks zu haben, um JavaScript zu bauen ....Ich wünschte nur, sie hätten es weiter gemacht, weil es schmerzhaft ist. – mpen

+0

@Mark: Eigentlich gibt es eine Demo :-) Laden Sie das Projekt unter http://code.google.com/p/django-dynamic-formset/ herunter und es enthält eine Django-Demo. –

+0

Das ist nicht, was ich mit einer Demo meinte. Ich meinte, ohne es herunterladen zu müssen ("Live-Demo"?). Es gibt Millionen von Projekten und Programmen ... die Leute wissen gerne, was sie bekommen, bevor sie in die Zeit und den Aufwand investieren und Dinge herunterladen und extrahieren und/oder installieren/kompilieren. Wie auch immer, da du es * empfohlen hast * und es ist nicht nur irgendeine zufällige Sache, über die ich gestolpert bin, werde ich es überprüfen ... (wenn es eine so wundervolle Bibliothek ist, würdest du erwarten, dass sie irgendwo benutzt wird, wo sie ist Könnte einfach verlinken ...) – mpen

1

in meinem Fall. Ich benutzte das Plugin django-dynamic-formset (https://code.google.com/p/django-dynamic-formset/wiki/Usage)

und änderte die Option "hinzugefügt" und funktionierte gut.

 $('#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); 

      }, 

dieser reguläre Ausdruck die Zeichenfolge [prefix] ersetzen - Präfix Peer '-' vielleicht

ist nicht die beste Lösung, aber gearbeitet.

1

Es gibt einige Fälle von möglichem XSS bei Verwendung von formset.empty_form als Zeichenfolge, wobei '__prefix__' durch den tatsächlichen Formset-Formindex ersetzt wird. Meine Pluggable-Anwendung konvertiert formset.empty_form in Knockout.js Vorlage, die dann über benutzerdefinierte Knockout.js Bindungen geklont wird. Außerdem berechnet Knockout.js automatisch Formularfeld-ID-Indizes neu, wenn das neu hinzugefügte Formularformular dynamisch gelöscht wird, bevor das gesamte Formular mit inlineformsets übergeben wurde. Hier ist die Dokumentation:

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

Knockout.js Bindung auch XSS verhindert, wenn benutzerdefinierte Felder mit Inline-Javascript geladen.

Verwandte Themen