如何使用基于类的视图处理表单(通过获取或发布)?

Jes*_*uez 34 django django-class-based-views

我试图学习基于类的视图,对于细节或列表视图并不复杂.

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

这是功能代码(不是我的,来自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))
Run Code Online (Sandbox Code Playgroud)

忽略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
Run Code Online (Sandbox Code Playgroud)

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

很公平,我今天开始用这些东西.

那么,制作基于类的视图的方法是什么,可以管理get(如果需要的话也可以发布)请求?

我有另一个例子:

@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()
Run Code Online (Sandbox Code Playgroud)

这会像第一个那样"转变"吗?或者他们扩展不同的观点?

我很困惑.我不知道第一个是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
Run Code Online (Sandbox Code Playgroud)

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

Ala*_*air 28

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

这很好地匹配了这个例子.在调用超类方法重定向到成功URL之前,您需要覆盖form_valid创建new 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)
Run Code Online (Sandbox Code Playgroud)

您的第一个示例与流程不匹配FormView,因为您没有处理包含POST数据的表单,并且在表单有效时您不执行任何操作.

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


mic*_*mit 9

注意,这里的答案(在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)
Run Code Online (Sandbox Code Playgroud)

这对我来说非常完美.(与本期相同的问题)

如上所述,这不是我的解决方案,如果你想给某人一些信用,请转到链接中的答案,并给这个人提供学分!(在FormView form_valid方法中更新上下文数据?)