web-dev-qa-db-ja.com

クラスベースビューの利点は何ですか?

今日私は、Django 1.3 alphaが出荷されていることを読みました。最も宣伝されている新機能は class-based views の導入です。
関連ドキュメント を読みましたが、それらを使用することで得られるbig Advantage™を確認するのは困難です。それで、私はそれらを理解するのにいくつかの助けをここに求めています。
ドキュメントから 高度な例 を見てみましょう。

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分で自分で作成した「プレーン・オールド・ビュー」ソリューションと比較してみましょう(エラーがあった場合はお詫びします)。

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))

私の2番目のバージョンは次のようになります。

  • 機能的に同等
  • より読みやすい(self.args[0]?ひどい!)
  • より短い
  • DRY準拠に劣らない

私が見逃している大きなものはありますか?なぜそれらを使用する必要があるのですか?それらはドキュメントにありますか?もしそうなら、理想的なユースケースは何でしょうか? mixinsは役に立ちますか?

貢献してくれた人に感謝します!

PS不思議に思うかもしれませんが、私も汎用ビューに夢中になることはありませんでした。いくつかの高度な機能が必要になるとすぐに、通常よりも短くなりませんでしたビュー。

81
Agos

クラスをサブクラス化して、特定の場合に合わせてget_context_dataなどのメソッドを調整し、残りをそのままにすることができます。関数でそれを行うことはできません。

たとえば、前のビューと同じことをすべて行う新しいビューを作成する必要があるかもしれませんが、コンテキストに追加の変数を含める必要があります。元のビューをサブクラス化し、get_context_dataメソッドをオーバーライドします。

また、テンプレートを別々のメソッドにレンダリングするために必要なステップを分離することで、コードがより明確になります。メソッドの実行が少ないほど、理解しやすくなります。通常のビュー機能では、すべて1つの処理ユニットにダンプされます。

48
Evan Porter

self.args[0]はあなたを悩ませています、代わりは次のとおりです:

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

次に、self.kwargs['slug']代わりに、少し読みやすくします。

17
Alex

関数とクラスの例は、機能が等しくありません。

クラスベースのバージョンは、ページネーションを無料で提供し、GET以外のHTTP動詞の使用を禁止します。

これを関数に追加する場合は、はるかに長くなります。

しかし、それは確かに、より複雑です。

10
e-satis

これは私がこれを聞いた最初のものです-そして私はそれが好きです。

正直なところ、私がここで見る利点は、ビューがDjango全体的により一貫性のあるものになることです。モデルはクラスであり、常にビューもそうである必要があると感じていました。そして、モデルは2つの頻繁に使用されるtypesです。

技術的な利点は?さて、Pythonすべてがクラス(またはオブジェクト?)です-本当に違いがあるのでしょうか?そもそも99%構文上の砂糖ではありませんか? ?

4
Frank V

クラスベースのビューについて考える1つの方法は、それらがDjangoトレーニングホイールをオフにした管理者のようなものであり、したがって、はるかに柔軟です(しかし、理解するのがより困難です)。

たとえば、adminのリスト表示は、明らかに汎用のListViewに基づいています。モデルまたはクエリセットのみを定義する最も単純なリストビュー。

class MyExampleView(ListView);
    model = ExampleModel 

独自のテンプレートを提供する必要がありますが、基本的には最も基本的なModelAdminと同じです。モデル管理のlist_display属性は、表示するフィールドを指示しますが、ListViewではテンプレートでこれを行います。

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

管理者にはパラメータがあります

list_per_page = 100

1ページあたりのオブジェクト数を定義します。リストビューには

paginate_by = 100

同じことを達成します。同様に、管理者を大幅にカスタマイズすることを検討すると、多くの重複が見られます。

ここのこのサイトは、彼らが何をしているのかについてのより良い考えをあなたに与えるでしょう。

http://ccbv.co.uk/

1
wobbily_col