Reputation: 7056
I am fairly new to Django and class based forms, and I am having trouble understanding how these interact with each other. Following from the django project example, I have tried to build a "search form", which would sit on all pages of my project:
# forms.py
from django import forms
class SearchForm(forms.Form):
myquery = forms.CharField(max_length=255,label="", help_text="sq")
def __unicode__(self):
return self.myquery
# views.py
from searchapp.forms import SearchForm
from django.views.generic.edit import FormView
from django.views.generic import TemplateView
class SearchView(FormView):
template_name = 'index.html'
form_class = SearchForm
success_url = '/searchres/'
def form_valid(self, form):
thequery=form.cleaned_data.get('myquery')
return super(SearchView, self).form_valid(form)
class Meta:
abstract = True
class SearchResView(SearchView):
template_name = 'searchres.html'
#urls.py
from django.conf.urls import patterns, include, url
from django.conf import settings
from deals.views import IndexView
from searchapp.views import SearchView, SearchResView
urlpatterns = patterns('',
url(r'^index/', SearchView.as_view(),name="home"),
url(r'^searchres/', SearchResView.as_view(),name="searchresx"),
)
The plan is the start off with a simple form for user to enter the search query, and also show the input form on the results page. I have the following questions here (sorry - I am a Django newbie esp. to Class Based Views):
Thank you in advance - I am hoping to learn more.
Upvotes: 1
Views: 2178
Reputation: 13328
I would suggest using function based views for this. If you choose to subclass a generic view you will need to dig through a lot of documentation and possibly source code, to find the right methods to override. (If you're really keen then look at the ListView
class along with the get_queryset()
, get()
and post()
methods)
A single django view will normally handle both rendering the empty form AND processing the submitted form.
So the search page (both the form and the results), live at http://your-site.com/search. Your url conf is -
urlpatterns = patterns('',
#...
(r'^search/$', 'searchapp.views.search'),
)
And your view looks something like this -
def search(request):
if request.method == 'POST':
form = SearchForm(request.POST)
if form.is_valid():
my_query = form.cleaned_data['myquery']
object_list = YourModel.objects.filter(# some operation involving my_query)
return render_to_response('search_results.html', {'object_list': object_list})
else:
form = SearchForm()
render_to_response('search_form.html', {'form': form})
(Note I've assumed your form method is post rather than get - I know this isn't great http but it's a common pattern with django)
To respond to your questions -
form.fields['myquery'].clean()
(or if you've called is_valid()
on your form, it's accessible with just form.cleaned_data['myquery']
).You want to try and avoid passing data for processing to the template. Do as much processing as you can in the view, then render the template. However if you want to pass myquery as a string for the template to render, then add it in to the context dictionary (the second non-key-word argument) in render_to_response
-
return render_to_response('search.html', {'object_list': object_list, 'myquery': my query})
The post data is constructed from the form fields. You don't have a form field thequery
. The view is processing the POST data - it's not creating it that's done by the html (which in turn is constructed by the Form class). Your variable thequery
is declared in the view.
Django's URL dispatcher ignores query strings in the URL so http://your_site.com/ssearch will be processed by the same view as http://your_site.com/search?myquery=findstuff. Simply change the html in the template from <form method='post'>
to and access the data in django with request.GET
. (You'll need to change the code from the view I described above to include a new check to see whether you're dealing with a form submission or just rendering a blank form)
Have a good read of the docs on views, forms and the url dispatcher.
Upvotes: 1