在Django 1.6中结合DetailView和CreateView

时间:2013-12-26 13:49:09

标签: python django django-class-based-views django-generic-views

我有2个独立的模型,帖子和评论。我使用DetailView显示Post内容,我想使用CreateView在同一页面上显示评论创建表单。最简洁的方法是什么?

唯一想到的是使用自定义视图,它既获取对象又处理注释表单,但这看起来太脏了:

def post_detail(request, slug):
    post = get_object_or_404(Post, slug=slug)
    if request.POST:
        form = CommentForm(request.POST)
        # do comment form processing here
    return render(request, "post/post_detail.html", {
        "object": post, "comment_form": form})

使用基于类的视图有没有干净的方法呢?或者只是某种方式将后期显示代码与评论处理代码分离?

2 个答案:

答案 0 :(得分:3)

一种选择是使用PostView的DetailView和模板标签来显示评论表单。让评论表单提交给评论CreateView,成功时重定向到DetailView。

那就是说,如果表格无效,可能会有点难看。在紧要关头,您始终可以从其中一个CreateView方法调用DetailView或其方法。但IMO引入了更多的耦合而不是更少。或者您可以使用单独的实用程序函数,如果注释表单有错误,您可以从CreateView调用以显示Post。

另一个选择是使用AJAX处理评论表单(在单独的CreateView中)而不是新的页面加载。

最后,无论语言或框架如何,对于需要显示一个对象类型并创建另一个对象类型的视图可以解耦多少都会有限制。

答案 1 :(得分:0)

可以合并DetailViewCreateView。您使用DetailView的类和CreateView的另一个类,然后创建一个继承自View的新类。这个新类有一个get和post方法。 get方法调用DetailView,而post方法调用CreateView。请注意对success_url中的CreateView使用reverse_lazy。所以基本上你的代码应该是这样的:

class PostView(DetailView):
    # your code 
    pass ;

class CommentView(CreateView):
    def get_success_url(self):
    return reverse_lazy('post_detail', kwargs={'pk': self.get_object(Post.objects.all().pk})

    pass

class PostCommentView(View):
    def get(self, request, *args, **kwargs):
         view = PostView.as_view()
         return view(request, *args, **kwargs) 

    def post(self, request, *args, **kwargs) :
         view = CommentView.as_view()
         return view(request, *args, **kwargs) 

所以你的urls.py会指向

PostCommentView 

我对get_success_url进行了覆盖,因为它会尝试转到不存在的新评论的详细视图,而不是您想要做的事情。因此,覆盖将带您进入帖子的详细视图。

文档中有解释

https://docs.djangoproject.com/en/2.0/topics/class-based-views/mixins/#an-alternative-better-solution