基于类的视图的优点是什么?

我今天看到Django 1.3 alpha正在发布,而最受欢迎的新function是引入基于类的视图 。
我已经阅读了相关的文档 ,但是我很难看到使用它们所能获得的巨大优势 ,所以我在这里请求帮助理解它们。
我们来看一个来自文档的高级示例 。

urls.py

from books.views import PublisherBookListView urlpatterns = patterns('', (r'^books/(\w+)/$', PublisherBookListView.as_view()), ) 

views.py

 from django.shortcuts import get_object_or_404 from django.views.generic import ListView from books.models import Book, Publisher class PublisherBookListView(ListView): context_object_name = "book_list" template_name = "books/books_by_publisher.html", def get_queryset(self): self.publisher = get_object_or_404(Publisher, name__iexact=self.args[0]) return Book.objects.filter(publisher=self.publisher) def get_context_data(self, **kwargs): # Call the base implementation first to get a context context = super(PublisherBookListView, self).get_context_data(**kwargs) # Add in the publisher context['publisher'] = self.publisher return context 

现在让我们来比较一下这个问题,我自己在5分钟内做出了一个“简单的旧观点”的解决scheme(我对你可能发现的任何错误表示歉意)。

urls.py

 urlpatterns = patterns('books.views', url(r'^books/(\w+)/$', 'publisher_books_list', name="publisher_books_list"), ) 

views.py

 from django.shortcuts import get_object_or_404 from books.models import Book, Publisher def publisher_books_list(request, publisher_name): publisher = get_object_or_404(Publisher, name__iexact=publisher_name) book_list = Book.objects.filter(publisher=publisher) return render_to_response('books/books_by_publisher.html', { "book_list": book_list, "publisher": publisher, }, context_instance=RequestContext(request)) 

对我来说第二个版本看起来:

  • 等同于function
  • 更可读( self.args[0] ?糟糕!)
  • 不less于DRY标准

有什么大的我失踪? 我为什么要使用它们? 那些在文档上? 如果是这样,那么理想的用例是什么? mixin有用吗?

提前感谢任何人的贡献!

对于那些可能想知道的人来说,我从来没有被普通的观点所吸引,只要我需要一些先进的function,他们就不会比普通的观点短。

你可以为一个类创build子类,然后像get_context_data一样对特定的情况进行细化,剩下的就是这样。 你不能用函数做到这一点。

例如,您可能需要创build一个新的视图来完成前一个视图的所有操作,但是您需要在上下文中包含额外的variables。 创build原始视图的子类并覆盖get_context_data方法。

另外,将模板渲染成单独的方法所需的步骤可以促进清晰的代码 – 在一个方法中做得越less,就越容易理解。 有了常规的查看function,它们都被转储到一个处理单元中。

如果self.args[0]困扰你,另一种方法是:

 urlpatterns = patterns('books.views', url(r'^books/(?P<slug>\w+)/$', 'publisher_books_list', name="publisher_books_list"), ) 

然后你可以使用self.kwargs['slug']来代替它,使它更具可读性。

您的示例函数和类在function上不相同。

基于类的版本免费提供分页,禁止使用GET以外的其他HTTP动词。

如果你想把它添加到你的函数中,将会更长。

但确实更复杂。

这是我听到的第一个 – 我喜欢它。

我在这里看到的优点,诚实地说,它使得视图与Django的整体更加一致。 模型是类,我一直认为,观点也应该是。 我知道不是一切都是,但意见和模型是两种常用的types

至于技术优势? 那么,在Python中,一切都是一个类( 或对象 ?) – 那么真的有区别吗? 是不是99%的语法糖呢?

考虑基于类的视图的一种方法是,它们就像是一个Djangopipe理员,具有训练轮子,因此更灵活(但更难以理解)。

例如,pipe理员中的列表显示显然是基于通用的ListView。 最简单的列表视图只能定义模型或查询集。

 class MyExampleView(ListView); model = ExampleModel 

您将需要提供自己的模板,但基本上与最基本的ModelAdmin相同。 模型admin中的list_display属性将告诉它显示哪些字段,而在ListView中,您将在模板中执行此操作。

 class SpeciesAdmin(admin.ModelAdmin): list_display = ['name'] admin.site.register(ExampleModel , ExampleModelAdmin) 

与pipe理员你有一个参数

 list_per_page = 100 

它定义每个页面有多less个对象。 列表视图有

 paginate_by = 100 

达到同样的目的。 同样,如果你看重pipe理员定制,你会看到很多重叠。

这里的这个网站应该能让你更好的了解他们的工作。

http://ccbv.co.uk/