plots - python plot numpy array




Django: mehrere Modelle in einer Vorlage unter Verwendung von Formularen (5)

"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 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 habe derzeit ein Workaround-Funktional (es besteht meine Unit-Tests). Es ist eine gute Lösung für meine Meinung, wenn Sie nur eine begrenzte Anzahl von Feldern aus anderen Modellen hinzufügen möchten.

Fehle ich hier etwas?

class UserProfileForm(ModelForm):
    def __init__(self, instance=None, *args, **kwargs):
        # Add these fields from the user object
        _fields = ('first_name', 'last_name', 'email',)
        # Retrieve initial (current) data from the user object
        _initial = model_to_dict(instance.user, _fields) if instance is not None else {}
        # Pass the initial data to the base
        super(UserProfileForm, self).__init__(initial=_initial, instance=instance, *args, **kwargs)
        # Retrieve the fields from the user model and update the fields with it
        self.fields.update(fields_for_model(User, _fields))

    class Meta:
        model = UserProfile
        exclude = ('user',)

    def save(self, *args, **kwargs):
        u = self.instance.user
        u.first_name = self.cleaned_data['first_name']
        u.last_name = self.cleaned_data['last_name']
        u.email = self.cleaned_data['email']
        u.save()
        profile = super(UserProfileForm, self).save(*args,**kwargs)
        return profile

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.








django-forms