2009-12-10 14 views
8

domanda newbie ....superare un valore iniziale ad una forma di campo Django Django

Sto cercando di scrivere un modulo di ricerca e mantenere lo stato della casella di input tra la richiesta di ricerca e risultati di ricerca.

Ecco la mia forma:

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

Ed ecco il mio codice di vista:

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

Ma questo mi dà l'errore:

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

Come posso passare il valore iniziale? Varie cose che ho provato sembrano interferire con il parametro request.POST.

risposta

9

Diverse cose non sono buone qui ...

1) La cosa consigliata dopo un post è per reindirizzare. Questo evita il famigerato popup che dice che stai inviando nuovamente il modulo quando usi il pulsante Indietro.

2) Non è necessario dire if request.method == 'POST', solo if request.POST. Questo rende il tuo codice più facile da leggere.

3) La vista si presenta generalmente qualcosa come:

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 

Questo non vuol dire che non ci può essere vista molto più semplice e molto più complicato. Ma questo è il succo di una vista: se la richiesta è post processare il modulo e il reindirizzamento; se la richiesta è avere il rendering del modulo.

Non so perché si sta verificando un errore Unicode. Posso solo pensare che sia legato a uno dei tuoi modelli che non fornisci. L'errore, come menziona spookylukey nel suo commento, molto probabilmente è causato dall'invio di una stringa invece di un dict al parametro iniziale.

Consiglio davvero la documentazione di django, in particular the tutorial., ma c'è anche il bellissimo Django Book.

Detto questo, penso che si desidera qualcosa di simile:

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

Si noti che il parametro iniziale è un dict dei valori dei campi del modulo.

Spero che questo aiuti.

+2

L'errore è dovuto al passaggio di un oggetto Unicode invece di un dict. (dict definisce 'get()', ma string/unicode no). – spookylukey

+0

Ah, ottimo punto. Ho visto l'errore ma non ho effettuato la connessione! – cethegeek

+0

Grazie per i commenti dettagliati e la soluzione. L'ho implementato in questo modo perché volevo che gli URL dei risultati fossero simili a/search/query (so che tuttavia ci sono problemi con questo, e potrebbe benissimo rivederlo). Devo reindirizzare dopo il POST, quindi non ci sono problemi con la pressione del pulsante Indietro. – AP257

5

I moduli di Django non sono particolarmente utili per il tuo caso d'uso. Inoltre, per una pagina di ricerca, è molto meglio utilizzare un modulo GET e mantenere lo stato nell'URL. Il seguente codice è molto più breve, più semplice ed è conforme agli standard di gran lunga migliore HTTP:

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

Il modello:

<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, in effetti sembra soddisfare le sue intenzioni meglio. – cethegeek

Problemi correlati