Django: Modellformular "Objekt hat kein Attribut 'bereinigte_Daten'"

83

Ich versuche, ein Suchformular für eine meiner Klassen zu erstellen. Das Modell des Formulars lautet:

from django import forms
from django.forms import CharField, ModelMultipleChoiceField, ModelChoiceField
from books.models import Book, Author, Category

class SearchForm(forms.ModelForm):
    authors = ModelMultipleChoiceField(queryset=Author.objects.all(),required=False)    
    category = ModelChoiceField (queryset=Category.objects.all(),required=False)
    class Meta:
        model = Book
        fields = ["title"]

Und die Ansicht, die ich benutze, ist:

from django.shortcuts import render_to_response, redirect, get_object_or_404
from django.template import RequestContext
from books.models import Book,Author
from books.forms import BookForm, SearchForm
from users.models import User

def search_book(request):
    if request.method == "POST":
        form = SearchForm(request.POST)
        if form.is_valid():
            form = SearchForm(request.POST)
            stitle = form.cleaned_data['title']
            sauthor = form.cleaned_data['author']
            scategory = form.cleaned_data['category']
    else:
        form = SearchForm()
    return render_to_response("books/create.html", {
        "form": form,
    }, context_instance=RequestContext(request))

Das Formular wird gut angezeigt, aber wenn ich es abschicke, erhalte ich eine Fehlermeldung: 'SearchForm' object has no attribute 'cleaned_data'

Ich bin mir nicht sicher, was los ist. Kann mir jemand helfen? Vielen Dank!

Joseph
quelle
8
Warum form = SearchForm(request.POST)zweimal anrufen ?
Hughdbrown
@SafwanSamsudeen Mein Kommentar sagt dasselbe wie die Antwort, die vor 10 Jahren als richtig akzeptiert wurde. Das Problem ist wirklich, dass der Code SearchForm nicht ein zweites Mal aufrufen sollte.
Hughbrown

Antworten:

178

Aus irgendeinem Grund instanziieren Sie das Formular nach dem Überprüfen erneut is_valid(). Formulare erhalten nur dann ein cleaned_dataAttribut, wenn is_valid()sie aufgerufen wurden, und Sie haben es in dieser neuen zweiten Instanz nicht aufgerufen.

Werde einfach die Sekunde los form = SearchForm(request.POST)und alles sollte gut sein.

Daniel Roseman
quelle
7

Ich würde den Code so schreiben:

def search_book(request):
    form = SearchForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        stitle = form.cleaned_data['title']
        sauthor = form.cleaned_data['author']
        scategory = form.cleaned_data['category']
        return HttpResponseRedirect('/thanks/')
    return render_to_response("books/create.html", {
        "form": form,
    }, context_instance=RequestContext(request))

Ziemlich ähnlich wie die Dokumentation .

hughdbrown
quelle
Nun, das funktioniert! Macht der Definitionsort der Form einen großen Unterschied?
Joseph
Ich weiß nicht, was Ihr Problem war, aber ich denke, dass ein SearchForm(request.POST)zweimaliger Anruf nicht notwendig war. Der Rest ist nur eine Schaufensterdekoration: Ich mag diese Art, die Argumente für die Formularkonstruktion so zu falten, dass Sie nur einen Aufruf benötigen.
Hughdbrown
Oder genau das, was @Daniel Roseman gesagt hat. Wenn ich Sie wäre, würde ich seine als bevorzugte Antwort auswählen, da er die genaue Ursache identifiziert.
Hughdbrown
2

Manchmal, wenn wir das vergessen

return self.cleaned_data 

In der sauberen Funktion von Django-Formularen werden wir keine Daten haben, obwohl die form.is_valid()zurückkehren werden True.

Subramanyam
quelle