Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass an initial value to a Django form field

Django newbie question....

I'm trying to write a search form and maintain the state of the input box between the search request and the search results.

Here's my form:

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

And here's my views 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,
        })

But this gives me the error:

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

How can I pass the initial value? Various things I've tried seem to interfere with the request.POST parameter.

like image 674
AP257 Avatar asked Dec 10 '09 17:12

AP257


1 Answers

Several things are not good here...

1) The recommended thing after a POST is to redirect. This avoids the infamous popup saying that you are resubmitting the form when using the back button.

2) You don't need to say if request.method == 'POST', just if request.POST. That makes your code easier to read.

3) The view generally looks something like:

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

That is not to say that there can't be much simpler and much more complicated views. But that is the gist of a view: if request is post process the form and redirect; if request is get render the form.

I don't know why you are getting an unicode error. I can only think that it is related to one of your models that you don't provide. The error, as spookylukey mentions is in his comment, most likely is caused by you submitting a string instead of a dict to the initial parameter.

I really recommend the django documentation, in particular the tutorial., but there is also the very nice Django Book.

All that said, I think you want something like:

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

Notice that the parameter to initial is a dict of the field values of your form.

Hope that helps.

like image 160
cethegeek Avatar answered Nov 08 '22 23:11

cethegeek