2009-12-10 12 views
8

Django newbie Frage ....Pass einen Anfangswert zu einem Feld Django Form

Ich versuche, ein Suchformular zu schreiben und den Zustand des Eingabefeldes zwischen der Suchanfrage und die Suchergebnisse zu erhalten.

Hier ist meine Form:

class SearchForm(forms.Form): 
    q = forms.CharField(label='Search: ', max_length=50) 

Und hier ist meine Ansichten Code:

def search(request, q=""): 
    if (q != ""): 
     q = q.strip() 
     form = SearchForm(initial=q) 
     #get results here... 
     return render_to_response('things/search_results.html', 
      {'things': things, 'form': form, 'query': q}) 
    elif (request.method == 'POST'): # If the form has been submitted 
     form = SearchForm(request.POST) 
     if form.is_valid(): 
      q = form.cleaned_data['q'] 
      # Process the data in form.cleaned_data 
      return HttpResponseRedirect('/things/search/%s/' % q) # Redirect after POST 
     else: 
      form = SearchForm() 
      return render_to_response('things/search.html', { 
      'form': form, 
      }) 
    else: 
     form = SearchForm() 
     return render_to_response('things/search.html', { 
      'form': form, 
     }) 

Aber das gibt mir den Fehler:

Caught an exception while rendering: 'unicode' object has no attribute 'get' 

Wie kann ich den Anfangswert übergeben? Verschiedene Dinge, die ich versucht habe, scheinen den Parameter request.POST zu stören.

Antwort

9

Mehrere Dinge sind hier nicht gut ...

1) Die empfohlene Sache nach einer POST umgeleitet ist. Dies vermeidet das berüchtigte Popup, das besagt, dass Sie das Formular erneut senden, wenn Sie die Zurück-Schaltfläche verwenden.

2) Sie müssen nicht if request.method == 'POST', nur if request.POST sagen. Das macht Ihren Code einfacher zu lesen.

3) Der Blick sieht im Allgemeinen so etwas wie:

def myview(request): 
    # Some set up operations 
    if request.POST: 
     form=MyForm(request.POST) 
     if form.is_valid(): 
      # some other operations and model save if any 
      # redirect to results page 
    form=MyForm() 
    #render your form template 

Das ist nicht zu sagen, dass es nicht viel einfacher sein kann und viel komplizierte Ansichten. Aber das ist der Kern einer Ansicht: Wenn Anfrage ist Postprozess das Formular und Redirect; wenn Anfrage erhalten wird, render das Formular.

Ich weiß nicht, warum Sie einen Unicode-Fehler bekommen. Ich kann nur denken, dass es sich um eines deiner Modelle handelt, die du nicht zur Verfügung stellst. Der Fehler, wie Spookylukey Erwähnungen in seinem Kommentar ist, wird höchstwahrscheinlich verursacht, indem Sie eine Zeichenfolge anstelle eines Diktats an den Anfangsparameter übergeben.

Ich empfehle wirklich die Django-Dokumentation, in particular the tutorial., aber es gibt auch die sehr nette Django Book.

Alles, was gesagt, ich glaube, Sie wollen so etwas wie:

def search(request, q=None): 
    if request.POST: 
     form = SearchForm(request.POST) 
     if form.is_valid(): 
      q = form.cleaned_data['q'] 
      url=reverse('search_results', args=(q,)) 
      return HttpResponseRedirect(url) 
    if q is None: 
     form = SearchForm() 
    else: 
     form = SearchForm(initial={'q': q}) 
    return render_to_response('things/search.html', { 
     'form': form, 
    }) 

Beachten Sie, dass der Parameter ein dict des Feldwertes des Formulars paraphieren.

Hoffe, dass hilft.

+2

Der Fehler wird durch eine Unicode-Objekt anstelle eines dict vorbei. (dict definiert 'get()', aber string/unicode nicht. – spookylukey

+0

Ah, ausgezeichneter Punkt. Ich habe den Fehler gesehen, aber die Verbindung nicht hergestellt! – cethegeek

+0

Danke für die ausführlichen Kommentare und die Lösung. Ich hatte es auf diese Weise implementiert, weil ich wollte, dass die Ergebnis-URLs wie/search/query aussehen (ich weiß, dass es dabei Probleme gibt und sie möglicherweise überarbeiten). Ich umadressiere nach dem POST, also gibt es kein Problem mit der Zurück-Taste. – AP257

5

Django-Formulare sind nicht besonders hilfreich für Ihren Anwendungsfall. Für eine Suchseite ist es außerdem viel besser, ein GET-Formular zu verwenden und den Status in der URL beizubehalten. Der folgende Code ist viel kürzer, einfacher und passt viel besser zu HTTP-Standards:

def search(request): 
    q = request.GET.get('q','').strip() 
    results = get_some_results(q) 
    render_to_response("things/search.html", {'q': q, 'results': results}) 

Die Vorlage:

<form method="GET" action="."> 
<p><input type="text" value="{{ q }}" /> <input type="submit" value="Search" /></p> 
{% if q %} 
    {% if results %} 
     Your results... 
    {% else %} 
     No results 
    {% endif %} 
{% endif %} 
</form> 
+0

+1, scheint tatsächlich seine Absichten besser zu erfüllen. – cethegeek

Verwandte Themen