Czytałem dzisiaj, że Django 1.3 alpha jest w sprzedaży, a najbardziej reklamowaną nową funkcją jest wprowadzenie widoków klasowych .
Przeczytałem odpowiednią dokumentację , ale trudno mi dostrzec wielką zaletę, jaką mogę uzyskać dzięki ich stosowaniu, dlatego proszę o pomoc w ich zrozumieniu.
Weźmy zaawansowany przykład z dokumentacji.
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
A teraz porównajmy to z rozwiązaniem „zwykłych starych poglądów”, wykonanym przeze mnie w ciągu 5 minut na to pytanie (przepraszam za każdy błąd, który można w nim znaleźć).
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))
Druga wersja dla mnie wygląda:
- Odpowiednik funkcjonalności
- O wiele bardziej czytelny (
self.args[0]
? Okropny!) - Krótszy
- Nie mniej zgodny z DRY
Czy brakuje mi czegoś dużego? Dlaczego powinienem ich używać? Czy to jest dokumentacja? Jeśli tak, to jaki byłby idealny przypadek użycia? Czy miksy są przydatne?
Z góry dziękuję każdemu, kto wnosi wkład!
PS dla tych, którzy mogą się zastanawiać, nigdy nie fascynowały mnie również widoki ogólne: gdy tylko potrzebowałem jakiejś zaawansowanej funkcjonalności, stały się nie krótsze niż zwykłe widoki.
Odpowiedzi:
Możesz podklasować klasę i udoskonalać metody, takie jak get_context_data, dla określonych przypadków, a resztę pozostawić bez zmian. Nie możesz tego zrobić za pomocą funkcji.
Na przykład może być konieczne utworzenie nowego widoku, który robi wszystko, co robi poprzedni, ale trzeba uwzględnić dodatkową zmienną w kontekście. Podklasuj oryginalny widok i nadpisz metodę get_context_data.
Ponadto rozdzielenie kroków potrzebnych do wyrenderowania szablonu na oddzielne metody sprzyja jaśniejszemu kodowi - im mniej wykonanych w metodzie, tym łatwiej jest ją zrozumieć. Dzięki zwykłym funkcjom widoku wszystko jest zrzucane do jednej jednostki przetwarzania.
źródło
Jeśli
self.args[0]
Ci przeszkadza, alternatywą jest:urlpatterns = patterns('books.views', url(r'^books/(?P<slug>\w+)/$', 'publisher_books_list', name="publisher_books_list"), )
Następnie możesz użyć
self.kwargs['slug']
zamiast tego, dzięki czemu będzie nieco bardziej czytelny.źródło
Twoja przykładowa funkcja i klasa nie są równe pod względem funkcji.
Wersja oparta na klasach zapewnia paginację za darmo i zabrania używania innych czasowników HTTP niż GET.
Jeśli chcesz dodać to do swojej funkcji, będzie to znacznie dłuższe.
Ale jest to rzeczywiście bardziej skomplikowane.
źródło
To jest pierwsza, o której słyszę - i mi się to podoba.
Zaletą, którą tutaj widzę, szczerze, jest to, że ogólnie rzecz biorąc, poglądy są bardziej spójne z Django. Modele to klasy i zawsze uważałem, że poglądy też powinny. Wiem, że nie wszystko jest, ale widoki i modele to dwa często używane typy .
A jeśli chodzi o przewagę techniczną? Cóż, w Pythonie wszystko jest klasą ( lub obiektem ?) - czy naprawdę jest różnica? Czy nie jest to przede wszystkim 99% cukier syntaktyczny?
źródło
Jednym ze sposobów myślenia o widokach opartych na klasach jest to, że są one jak administrator Django z wyłączonym szkoleniem, a zatem o wiele bardziej elastyczne (ale trudniejsze do zrozumienia).
Na przykład wyświetlanie listy w panelu administracyjnym jest wyraźnie oparte na ogólnym ListView. W najprostszym widoku listy zdefiniowałbyś tylko model lub zestaw zapytań.
class MyExampleView(ListView); model = ExampleModel
Będziesz musiał dostarczyć swój własny szablon, ale będzie on zasadniczo taki sam, jak najbardziej podstawowy ModelAdmin. Atrybut list_display w administratorze modelu powie mu, które pola mają być wyświetlane, podczas gdy w ListView zrobiłbyś to w szablonie.
class SpeciesAdmin(admin.ModelAdmin): list_display = ['name'] admin.site.register(ExampleModel , ExampleModelAdmin)
Z administratorem masz parametr
list_per_page = 100
który określa, ile obiektów na stronę. Widok listy ma
paginate_by = 100
co daje to samo. Podobnie, jeśli przyjrzysz się dostosowaniu administratora, zobaczysz wiele nakładek.
Ta strona powinna dać ci lepsze wyobrażenie o tym, co robią.
http://ccbv.co.uk/
źródło