2010-11-29 12 views
55

J'essaie de faire un formulaire de recherche pour l'une de mes classes. Le modèle de la forme est:Django: Model Form "l'objet n'a pas d'attribut 'clean_data'"

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"] 

Et la vue que je utilise est:

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)) 

La forme se présente bien, mais quand je le soumets je reçois une erreur: 'SearchForm' object has no attribute 'cleaned_data'

Je ne sais pas ce qui se passe, quelqu'un peut-il m'aider? Merci!

+5

Pourquoi appeler 'form = SearchForm (request.POST)' deux fois? – hughdbrown

Répondre

118

Pour une raison quelconque, vous réinstallez le formulaire après avoir vérifié is_valid(). Les formulaires n'obtiennent un attribut cleaned_data que lorsque is_valid() a été appelé et vous ne l'avez pas appelé sur cette nouvelle instance.

Il suffit de se débarrasser de la seconde form = SearchForm(request.POST) et tout devrait bien se passer.

+0

Ah, ça l'explique. Merci beaucoup, juste un oubli stupide. – Joseph

+4

détail extrêmement important merci – soField

4

Je voudrais écrire le code comme ceci:

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)) 

Un peu comme le documentation.

+0

Eh bien, ça marche! Est-ce que l'emplacement de définition de la forme fait une grande différence? – Joseph

+0

Je ne sais pas quel était votre problème, mais je pense qu'appeler deux fois SearchForm (request.POST) n'était pas nécessaire. Le reste n'est qu'une façade: il m'arrive d'aimer cette façon de plier les arguments de construction de formulaire pour que vous n'ayez besoin que d'un seul appel. – hughdbrown

+0

Ou exactement ce que dit @Daniel Roseman. Si j'étais vous, je choisirais son comme réponse préférée parce qu'il identifie la cause précise. – hughdbrown

1

Parfois, si l'on oublie la

return self.cleaned_data 

dans la fonction propre des formes django, nous pas de données si le form.is_valid() retournera True.