在类基表单之间传递数据
我对Django和基于类的表单还比较陌生,现在有些困惑,不太明白它们是怎么互动的。根据Django项目示例,我尝试创建一个“搜索表单”,希望它能出现在我项目的所有页面上:
# 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"),
)
我的计划是先做一个简单的表单,让用户输入搜索内容,并且在结果页面也显示这个输入表单。我有以下几个问题(抱歉,我是Django新手,尤其是对基于类的视图):
- 如何把数据(“thequery”)传递给success_url?也就是说,我希望success_url能访问到“thequery”,这样我就可以在模板标签中使用类似{{thequery}}的东西。
- 在提交表单(name="home")后,我在firebug中看到了表单的POST数据,但我只看到“myquery”,而不是“thequery”。在这里,如何使用get_context_data()来添加或传递“thequery”变量呢?
- 最后,我想知道是否可以根据“thequery”字符串构建success_url,比如像这样:success_url = '/searchres/?q=' + thequery。
提前谢谢你们——我希望能学到更多。
1 个回答
我建议你使用基于函数的视图来处理这个问题。如果你选择去继承一个通用视图,你可能需要翻阅很多文档,甚至是源代码,才能找到合适的方法来重写。(如果你真的很感兴趣,可以看看 ListView
类以及 get_queryset()
、get()
和 post()
方法)
一个单独的 Django 视图通常会同时处理显示空表单和处理提交的表单。
所以搜索页面(包括表单和结果)会在 http://your-site.com/search 这个地址上。你的 URL 配置是 -
urlpatterns = patterns('',
#...
(r'^search/$', 'searchapp.views.search'),
)
而你的视图看起来大概是这样的 -
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})
(注意我假设你的表单方法是 POST 而不是 GET - 我知道这不是最好的 HTTP 方式,但在 Django 中这是个常见的做法)
针对你的问题 -
- 不要自己写方法来清理数据。给你的表单添加一个 clean_myquery 方法,然后用
form.fields['myquery'].clean()
来访问它(或者如果你已经调用过is_valid()
方法,那么可以直接用form.cleaned_data['myquery']
来获取)。
你要尽量避免把数据传给模板去处理。尽可能在视图中处理好数据,然后再渲染模板。不过,如果你想把 myquery 作为字符串传给模板渲染,那么就把它放进上下文字典(第二个非关键字参数)里,在 render_to_response
中 -
return render_to_response('search.html', {'object_list': object_list, 'myquery': my query})
POST 数据是由表单字段构成的。你没有一个表单字段叫
thequery
。视图在处理 POST 数据,而不是创建它,这个是由 HTML 生成的(而 HTML 又是由表单类构建的)。你的变量thequery
是在视图中声明的。Django 的 URL 分发器会忽略 URL 中的查询字符串,所以 http://your_site.com/ssearch 会被和 http://your_site.com/search?myquery=findstuff 同样的视图处理。只需把模板中的 HTML 从
<form method='post'>
改成,然后用request.GET
在 Django 中访问数据。(你需要修改我上面描述的视图代码,加入一个新的检查,以确定你是在处理表单提交还是仅仅渲染一个空表单)