37

我正在尝试学习基于类的视图,因为详细信息或列表视图并不复杂。

我有一个搜索表单,我只想看看我是否发送查询以显示结果。

这是函数代码(不是我的,来自 django 书):

def search_page(request):
    form = SearchForm()
    bookmarks = []
    show_results = False
    if 'query' in request.GET:
        show_results = True
        query = request.GET['query'].strip()
        if query:
            form = SearchForm({'query': query})
            bookmarks = Bookmark.objects.filter(title__icontains=query)[:10]


    show_tags = True
    show_user = True

    if request.is_ajax():
        return render_to_response("bookmarks/bookmark_list.html", locals(), context_instance=RequestContext(request))
    else:
        return render_to_response("search/search.html", locals(), context_instance=RequestContext(request))

忽略 ajax 事实(只是为了让问题更容易现在),我如何将其转换为基于类的视图?

我很快尝试了这样的事情:

class SearchPageView(FormView):
    template_name = 'search/search.html'

    def get(self, request, *args, **kwargs):
        form = SearchForm()
        self.bookmarks = []
        self.show_results = False
        if 'query' in self.request.GET:
            self.show_results = True
            query = self.request.GET['query'].strip()
            if query:
                form = SearchForm({'query': query})
                self.bookmarks = Bookmark.objects.filter(title__icontains=query)[:10]
        return super(SearchPageView, self).get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(SearchPageView, self).get_context_data(**kwargs)
        context.update({
            'show_tags': True,
            'show_user': True,
            'show_results': self.show_results,
            'bookmarks': self.bookmarks
        })
        return context

不起作用,我得到一个:“'NoneType' 对象不可调用”

很公平,我今天从这些东西开始。

那么,有什么方法可以创建一个基于类的视图来管理获取(如果需要也可以发布)请求?

我还有一个例子:

@render_to('registration/register.html')
def register_page(request):
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            user = User.objects.create_user(
                username=form.cleaned_data['username'],
                password=form.cleaned_data['password1'],
                email=form.cleaned_data['email']
            )
            return HttpResponseRedirect('/accounts/register/success/')
    else:
        form = RegistrationForm()
    return locals()

这会以与第一个相同的方式“转换”吗?或者他们扩展了不同的视图?

我很困惑。我不知道第一个是 ProcessFormView 和第二个 FormView 还是什么。

谢谢。

编辑:我结束的解决方案:

class SearchPageView(FormView):
    template_name = 'search/search.html'

    def get(self, request, *args, **kwargs):
        self.bookmarks = []
        self.show_results = False
        form = SearchForm(self.request.GET or None)
        if form.is_valid():
            self.show_results = True
            self.bookmarks = Bookmark.objects.filter(title__icontains=form.cleaned_data['query'])[:10]

        return self.render_to_response(self.get_context_data(form=form))


    def get_context_data(self, **kwargs):
        context = super(SearchPageView, self).get_context_data(**kwargs)
        context.update({
            'show_tags': True,
            'show_user': True,
            'show_results': self.show_results,
            'bookmarks': self.bookmarks
        })
        return context

我把这个留给有同样问题的人:)

4

2 回答 2

32

该类的默认行为FormView是为GET请求显示未绑定的表单,并为POST(或PUT)请求绑定表单。如果绑定的表单有效,则form_valid调用该方法,该方法简单地重定向到成功 url(由success_url属性或get_success_url方法定义。

这与示例非常匹配。在调用超类方法重定向到成功 url 之前,您需要重写该form_valid方法以创建新的 。User

class CreateUser(FormView):
    template_name = 'registration/register.html'
    success_url = '/accounts/register/success/'
    form_class = RegistrationForm

    def form_valid(self, form):
        user = User.objects.create_user(
                username=form.cleaned_data['username'],
                password=form.cleaned_data['password1'],
                email=form.cleaned_data['email']
        )
        return super(CreateUser, self).form_valid(form)

您的第一个示例与流程不太匹配FormView,因为您没有处理带有POST数据的表单,并且当表单有效时您不做任何事情。

我可能会尝试扩展TemplateView,并将所有逻辑放入get_context_data. 一旦你开始工作,你可以将解析 GET 数据并将书签返回到它自己的方法中的代码分解。您可以查看 extended ListView,但除非您想对结果进行分页,否则我认为没有任何真正的优势。

于 2012-01-18T00:50:07.457 回答
14

注意,这里的答案(在 FormView form_valid 方法中更新上下文数据?)解决了这个问题,如下所示:

class ContextFormView(FormView):
    template_name = 'some_template.html'
    success_url = '...'
    form_class = ClassOfTheForm

    def get(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        context = self.get_context_data(**kwargs)
        context['form'] = form
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        if form.is_valid():
            return self.form_valid(form, **kwargs)
        else:
            return self.form_invalid(form, **kwargs)


    def form_invalid(self, form, **kwargs):
        context = self.get_context_data(**kwargs)
        context['form'] = form
        # here you can add things like:
        context[show_results] = False
        return self.render_to_response(context)

    def form_valid(self, form, **kwargs):
        context = self.get_context_data(**kwargs)
        context['form'] = form
        # here you can add things like:
        context[show_results] = True
        return self.render_to_response(context)

这对我来说很完美。(与此问题相同的问题)

如上所述,这不是我的解决方案,如果您想给某人积分,请转到链接中的答案并给此人积分!(在 FormView form_valid 方法中更新上下文数据?

于 2015-01-03T21:29:51.350 回答