在类基表单之间传递数据

1 投票
1 回答
2157 浏览
提问于 2025-04-17 15:34

我对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 个回答

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 中这是个常见的做法)

针对你的问题 -

  1. 不要自己写方法来清理数据。给你的表单添加一个 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})
  1. POST 数据是由表单字段构成的。你没有一个表单字段叫 thequery。视图在处理 POST 数据,而不是创建它,这个是由 HTML 生成的(而 HTML 又是由表单类构建的)。你的变量 thequery 是在视图中声明的。

  2. Django 的 URL 分发器会忽略 URL 中的查询字符串,所以 http://your_site.com/ssearch 会被和 http://your_site.com/search?myquery=findstuff 同样的视图处理。只需把模板中的 HTML 从 <form method='post'> 改成,然后用 request.GET 在 Django 中访问数据。(你需要修改我上面描述的视图代码,加入一个新的检查,以确定你是在处理表单提交还是仅仅渲染一个空表单)

好好阅读一下关于 视图表单URL 分发器 的文档。

撰写回答