У чому перевага поглядів на основі класів?


83

Сьогодні я прочитав, що Django 1.3 alpha постачається, і найрекламнішою новою функцією є введення поглядів на основі класів .
Я прочитав відповідну документацію , але мені важко зрозуміти велику перевагу ™, яку я міг би отримати, використовуючи їх, тому я прошу тут допомогу в їх розумінні.
Візьмемо передовий приклад із документації.

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

Друга версія для мене виглядає:

  • Еквівалент за функціональністю
  • Набагато читабельніше ( self.args[0]? Жахливо!)
  • Коротше
  • Не менш сухий

Щось великого мені не вистачає? Чому я повинен їх використовувати? Чи є це в документації? Якщо так, то який би був ідеальний варіант використання? Чи корисні міксіни ?

Заздалегідь дякуємо всім, хто робить свій внесок!

PS для тих, хто може здивуватися, мене ніколи не захоплювали і загальні погляди: як тільки мені знадобилася якась розширена функціональність, вони стали не коротшими за звичайні перегляди.


4
Так, я теж не бачу великої переваги. Хотілося б побачити велику відповідь на це.
M. Ryan

1
Повністю згоден. Мені особливо огидно self.args [0] або self.kwargs ['slug']. Тепер також набагато складніше надати значення за замовчуванням для параметрів url, наприклад: def publisher_books_list (request, publisher_name = 'Herbert')
Кевін Ренкерс,

Відповіді:


49

Ви можете підклас класу і уточнити методи, такі як get_context_data для конкретних випадків, а решта залишити як є. Це неможливо зробити за допомогою функцій.

Наприклад, вам може знадобитися створити нове представлення, яке робить все, що робить попереднє, але вам потрібно включити додаткову змінну в контекст. Підклас вихідного подання і замінити метод get_context_data.

Крім того, поділ кроків, необхідних для візуалізації шаблону, на окремі методи сприяє більш чіткому коду - чим менше зроблено методу, тим легше його зрозуміти. Завдяки звичайним функціям перегляду це все передається в один процесор.


2
Так, я це бачу. Це полегшує заміну та часте змішування, якщо ви намагаєтесь вирішити, чи варто вам перейти на RESTful, мати повний сайт або мобільний сайт. Таким чином, це рішення можна відкласти якомога довше, поки функціонал буде отриманий. Модуль веб-програм у Pylons мав це, і це було дуже корисно. Тим не менш, перегляди на основі класів давно стали можливими з Django, замінивши метод __call __ ().
Elf Sternberg

9
Прийняття відповіді, оскільки вона дає дуже хороший момент ... але все одно не відчуваю необхідності їх використовувати, оскільки мені рідко доводиться вирішувати такі проблеми. Дякую!
Agos

18

Якщо self.args[0]вас турбує, альтернативою є:

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

Тоді ви могли б використовувати self.kwargs['slug'] замість цього, роблячи його трохи більш читабельним.


10

Ваша прикладна функція та клас не рівні за ознаками.

Версія, що базується на класі, надає пагінацію безкоштовно і забороняє використання інших дієслів HTTP, крім GET.

Якщо ви хочете додати це до своєї функції, це буде набагато довше.

Але це, справді, складніше.


2
+1 за вказівку на різницю, але особисто я думаю, що require_GET та django-пагінація є тривіальними у використанні, стислими, явними тощо, і я віддаю перевагу їм cbvs на (майже :)) весь час.
Томаш Зелінський

4

Це перше, про що я чую - і мені це подобається.

Чесна перевага, яку я тут бачу, полягає в тому, що вона робить погляди більш загальними з Django. Моделі - це класи, і я завжди вважав, що погляди теж повинні бути. Я знаю, що не все є, але види та моделі - це два широко використовувані типи .

Що стосується технічної переваги? Що ж, у Python все є класом ( або об’єктом ?) - то чи справді є різниця? Чи не насамперед це 99% синтаксичний цукор?


Я б сказав, що узгодженість дозволяє більше використовувати повторний код. Вони в основному скорочують багато шаблонів, якщо ваші погляди відповідають певним шаблонам. наприклад, форма, заснована на моделі aa, надзвичайно швидко генерується з поданнями на основі класу. Якщо йому потрібна пара додаткових полів, вона починає ставати дещо складнішою. Якщо вам потрібна форма, заснована на трьох моделях та двох додаткових полях, вони, ймовірно, зовсім не заощадять вам багато зусиль.
wobbily_col

1

Одним із способів думати про погляди на основі класів є те, що вони схожі на адміністратора Django з відключеними навчальними колесами, а отже, набагато гнучкішими (але важчими для розуміння).

Наприклад, відображення списку в адміністраторі чітко базується на загальному 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

який визначає, скільки об’єктів на сторінці. Перегляд списку має

paginate_by = 100

який досягає того самого. Аналогічним чином, якщо ви глибоко налаштуєте адміністратора, ви побачите багато перекриттів.

Цей сайт тут повинен дати вам краще уявлення про те, чим вони займаються.

http://ccbv.co.uk/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.