主视图是一个简单的分页ListView,我想在其中添加一个搜索表单。
我觉得这样做就可以了:
class MyListView(ListView, FormView):
form_class = MySearchForm
success_url = 'my-sucess-url'
model = MyModel
# ...
但显然我搞错了...而且我在官方文档中找不到如何做到这一点。
有什么建议吗?
这些答案帮助我朝着正确的方向前进了很多,谢谢大家。
为了我的实现,我需要一个表单视图,在get和post时都返回一个ListView。我不喜欢重复get函数的内容,但它需要一些改变。现在,表单也可以从self.form中的get_queryset获取。
from django.http import Http404
from django.utils.translation import ugettext as _
from django.views.generic.edit import FormMixin
from django.views.generic.list import ListView
class FormListView(FormMixin, ListView):
def get(self, request, *args, **kwargs):
# From ProcessFormMixin
form_class = self.get_form_class()
self.form = self.get_form(form_class)
# From BaseListView
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty and len(self.object_list) == 0:
raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.")
% {'class_name': self.__class__.__name__})
context = self.get_context_data(object_list=self.object_list, form=self.form)
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs)
class MyListView(FormListView):
form_class = MySearchForm
model = MyModel
# ...
我也一直在寻找合适的解决方案,但是没有找到,因此只能自己想办法。
views.py
class VocationsListView(ListView):
context_object_name = "vocations"
template_name = "vocations/vocations.html"
paginate_by = 10
def get_queryset(self):
get = self.request.GET.copy()
if(len(get)):
get.pop('page')
self.baseurl = urlencode(get)
model = Vocation
self.form = SearchForm(self.request.GET)
filters = model.get_queryset(self.request.GET)
if len(filters):
model = model.objects.filter(filters)
else:
model = model.objects.all()
return model
def get_context_data(self):
context = super(VocationsListView, self).get_context_data()
context['form'] = self.form
context['baseurl']= self.baseurl
return context
models.py
class Vocation(models.Model):
title = models.CharField(max_length = 255)
intro = models.TextField()
description = models.TextField(blank = True)
date_created = models.DateTimeField(auto_now_add = True)
date_modified = models.DateTimeField(auto_now = True)
created_by = models.ForeignKey(User, related_name = "vocation_created")
modified_by = models.ForeignKey(User, related_name = "vocation_modified")
class Meta:
db_table = "vocation"
@property
def slug(self):
return defaultfilters.slugify(self.title)
def __unicode__(self):
return self.title
@staticmethod
def get_queryset(params):
date_created = params.get('date_created')
keyword = params.get('keyword')
qset = Q(pk__gt = 0)
if keyword:
qset &= Q(title__icontains = keyword)
if date_created:
qset &= Q(date_created__gte = date_created)
return qset
所以基本上我会将这段代码添加到每个模型类中,我想要实现搜索功能的地方。这是因为每个模型的过滤器都必须显式地准备好。
@staticmethod
def get_queryset(params):
date_created = params.get('date_created')
keyword = params.get('keyword')
qset = Q(pk__gt = 0)
if keyword:
qset &= Q(title__icontains = keyword)
if date_created
qset &= Q(date_created__gte = date_created)
return qset
它准备了我用来从模型中检索数据的QSet过滤器。
get
请求是有效的):from django.views.generic import ListView
from django.views.generic.edit import FormMixin
from .models import MyModel
from .forms import MySearchForm
class ListPageView(FormMixin, ListView):
template_name = 'property_list.html'
model = MyModel
form_class = MySearchForm
queryset = MyModel.objects.all()
在ListView
之前使用FormMixin
。如果你想在TemplateView
中使用SearchForm
,可以这样做:
from django.views.generic.base import TemplateView
from django.views.generic.edit import FormMixin
from .models import MyModel
from .forms import MySearchForm
class HomePageView(FormMixin, TemplateView):
template_name = 'home.html'
form_class = MySearchForm
根据之前的回答,以下是我对于在同一页面上显示表单的视图的看法:
class IndexView(FormMixin, ListView):
''' Homepage: displays list of links, and a form used to create them '''
template_name = "links/index.html"
context_object_name = "links"
form_class = LinkForm
def get_queryset(self):
return Links.objects.all()
def add_link(request):
# Sole job of this function is to process the form when POSTed.
if request.method == "POST":
form = LinkForm(request.POST)
if form.is_valid():
Links.objects.create(address=form.cleaned_data['address'])
return HttpResponseRedirect('/')
然后,最后一步是将add_link视图函数绑定到表单的操作URL上,这样就可以进行操作了。
在 官方文档中介绍了使用混合类将表单添加到索引和列表视图中。但是,文件通常建议不采用这种方法。它建议手动编写更多的Python代码并手工编码视图。
(FormMixin, DetailView)
,而不是 ListView
。 - ArtOfWarfare
post(self, request, *args, **kwargs)
方法。但是怎么做呢?从get方法中复制代码并在那里进行搜索吗?有时候我的印象是,LisViews最终会比编写简单视图函数更加复杂。或者我错过了什么? - Jens-Erik Weber