python matplotlib - Django:mehrere Modelle in einer Vorlage unter Verwendung von Formularen




example install (7)

Das ist mit ModelForms nicht zu schwer zu implementieren. Nehmen wir an, Sie haben die Formulare A, B und C. Sie drucken jedes der Formulare und der Seite aus, und jetzt müssen Sie den POST bearbeiten.

if request.POST():
    a_valid = formA.is_valid()
    b_valid = formB.is_valid()
    c_valid = formC.is_valid()
    # we do this since 'and' short circuits and we want to check to whole page for form errors
    if a_valid and b_valid and c_valid:
        a = formA.save()
        b = formB.save(commit=False)
        c = formC.save(commit=False)
        b.foreignkeytoA = a
        b.save()
        c.foreignkeytoB = b
        c.save()

Here sind die Dokumente für die benutzerdefinierte Validierung.

Ich erstelle eine Support-Ticket-Tracking-App und habe ein paar Modelle, die ich von einer Seite erstellen möchte. Tickets gehören einem Kunden über einen ForeignKey. Notizen gehören auch zu Tickets über ForeignKey. Ich möchte die Möglichkeit haben, einen Kunden auszuwählen (das ist ein ganz separates Projekt) ODER einen neuen Kunden zu erstellen, dann ein Ticket zu erstellen und schließlich eine Notiz zu erstellen, die dem neuen Ticket zugewiesen wird.

Da ich ziemlich neu in Django bin, tendiere ich dazu, iterativ zu arbeiten und jedes Mal neue Funktionen auszuprobieren. Ich habe mit ModelForms gespielt, möchte aber einige Felder ausblenden und eine komplexe Validierung durchführen. Es scheint so, als ob das Maß an Kontrolle, das ich suche, Formsets erfordert oder alles von Hand erledigt, komplett mit einer mühsamen, handcodierten Templateseite, die ich vermeiden möchte.

Gibt es eine schöne Eigenschaft, die ich vermisse? Hat jemand eine gute Referenz oder ein Beispiel für die Verwendung von Formsets? Ich verbrachte ein ganzes Wochenende mit den API-Dokumenten für sie und ich bin immer noch ahnungslos. Ist es ein Designproblem, wenn ich alles kaputt mache und handkodiert habe?



Das MultiModelForm von django-betterforms ist ein praktischer Wrapper, um das zu tun, was in Gnudiffs Antwort beschrieben wird . Es ModelForm reguläre ModelForm in einer einzigen Klasse ein, die transparent (zumindest für die grundlegende Verwendung) als einzelnes Formular verwendet wird. Ich habe unten ein Beispiel aus ihren Dokumenten kopiert.

# forms.py
from django import forms
from django.contrib.auth import get_user_model
from betterforms.multiform import MultiModelForm
from .models import UserProfile

User = get_user_model()

class UserEditForm(forms.ModelForm):
    class Meta:
        fields = ('email',)

class UserProfileForm(forms.ModelForm):
    class Meta:
        fields = ('favorite_color',)

class UserEditMultiForm(MultiModelForm):
    form_classes = {
        'user': UserEditForm,
        'profile': UserProfileForm,
    }

# views.py
from django.views.generic import UpdateView
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import redirect
from django.contrib.auth import get_user_model
from .forms import UserEditMultiForm

User = get_user_model()

class UserSignupView(UpdateView):
    model = User
    form_class = UserEditMultiForm
    success_url = reverse_lazy('home')

    def get_form_kwargs(self):
        kwargs = super(UserSignupView, self).get_form_kwargs()
        kwargs.update(instance={
            'user': self.object,
            'profile': self.object.profile,
        })
        return kwargs

Ich hatte vor kurzem das Problem und habe gerade herausgefunden, wie das geht. Angenommen, Sie haben drei Klassen: Primary, B, C und B, C haben einen Fremdschlüssel für die Primary

    class PrimaryForm(ModelForm):
        class Meta:
            model = Primary

    class BForm(ModelForm):
        class Meta:
            model = B
            exclude = ('primary',)

    class CForm(ModelForm):
         class Meta:
            model = C
            exclude = ('primary',)

    def generateView(request):
        if request.method == 'POST': # If the form has been submitted...
            primary_form = PrimaryForm(request.POST, prefix = "primary")
            b_form = BForm(request.POST, prefix = "b")
            c_form = CForm(request.POST, prefix = "c")
            if primary_form.is_valid() and b_form.is_valid() and c_form.is_valid(): # All validation rules pass
                    print "all validation passed"
                    primary = primary_form.save()
                    b_form.cleaned_data["primary"] = primary
                    b = b_form.save()
                    c_form.cleaned_data["primary"] = primary
                    c = c_form.save()
                    return HttpResponseRedirect("/viewer/%s/" % (primary.name))
            else:
                    print "failed"

        else:
            primary_form = PrimaryForm(prefix = "primary")
            b_form = BForm(prefix = "b")
            c_form = Form(prefix = "c")
     return render_to_response('multi_model.html', {
     'primary_form': primary_form,
     'b_form': b_form,
     'c_form': c_form,
      })

Mit dieser Methode können Sie die von Ihnen benötigte Validierung durchführen und alle drei Objekte auf derselben Seite generieren. Ich habe auch Javascript und versteckte Felder verwendet, um die Erzeugung mehrerer B, C Objekte auf derselben Seite zu ermöglichen.


"Ich möchte einige der Felder verstecken und eine komplexe Validierung durchführen."

Ich beginne mit der integrierten Admin-Oberfläche.

  1. Erstellen Sie das ModelForm, um die gewünschten Felder anzuzeigen.

  2. Erweitern Sie das Formular mit den Validierungsregeln innerhalb des Formulars. Normalerweise ist dies eine clean Methode.

    Stellen Sie sicher, dass dieser Teil einigermaßen gut funktioniert.

Sobald dies erledigt ist, können Sie sich von der integrierten Admin-Oberfläche entfernen.

Dann können Sie mit mehreren, teilweise verwandten Formularen auf einer einzigen Webseite herumspielen. Dies ist eine Sammlung von Vorlagen, um alle Formulare auf einer Seite zu präsentieren.

Dann müssen Sie die View-Funktion schreiben, um die verschiedenen Form-Dinge zu lesen und zu validieren und die verschiedenen Objekt-Saves () auszuführen.

"Ist es ein Design-Problem, wenn ich alles kaputt mache und alles handkodiert habe?" Nein, es ist nur eine Menge Zeit für wenig Nutzen.


Ich war gerade in der gleichen Situation vor einem Tag, und hier sind meine 2 Cent:

1) Ich fand wohl die kürzeste und prägnanteste Demonstration des multiplen Modelleintrags in Einzelform: http://collingrady.wordpress.com/2008/02/18/editing-multiple-objects-in-django-with-newforms/ .

Kurz zusammengefasst: Erstellen Sie für jedes Modell ein Formular, senden Sie beide Vorlagen in einem einzigen <form> -Format mit dem prefix keyarg und lassen Sie die View-Handle-Validierung durchführen. Wenn es eine Abhängigkeit gibt, stellen Sie sicher, dass Sie das "Eltern" -Modell vor der Abhängigkeit speichern und die ID der Eltern für den Fremdschlüssel verwenden, bevor Sie das Speichern des "Kind" -Modells veranlassen. Der Link hat die Demo.

2) Vielleicht können Formsets dafür eingesetzt werden, aber so weit ich mich eingehender geäußert habe, sind Formsets in erster Linie für die Eingabe von Vielfachen des gleichen Modells gedacht, das optional durch Fremdschlüssel mit einem anderen Modell / anderen Modellen verknüpft werden kann . Es scheint jedoch keine Standardoption für die Eingabe von mehr als einem Modell Daten zu geben, und das ist nicht das, was Formset zu sein scheint.


+1 auf S.Lotts Vorschlag einer benannten Container-Klasse.

Für python 2.6 und höher bietet ein benanntes Tupel eine nützliche Möglichkeit zum einfachen Erstellen dieser Container-Klassen, und die Ergebnisse sind "leichtgewichtig und benötigen keinen Speicher mehr als normale Tupel".







python django design django-forms