Автор оригинала: James Ezechukwu.
Мы часто обнаруживаем, что разработчики Django, особенно новички в фреймворке, и даже некоторые продвинутые пользователи предпочитают использовать представления на основе функций (FBV) для большинства проектов. Это можно объяснить, во-первых, простотой использования FBV и отсутствием понимания больших преимуществ использования представлений на основе классов.(CBV) В этом посте я выделю некоторые из основных преимуществ и интересных функций CBV. В этом посте также будет предпринята попытка упростить некоторые из наиболее неправильно понятых концепций CBV. Мы рассмотрим случаи, когда CBV предпочтительнее FBV, а в противном случае.
Некоторые преимущества использования представления на основе классов
- Возможность повторного использования кода – В CBV класс представления может быть унаследован другим классом представления и изменен для другого варианта использования.
- СУХОЕ использование CBV помогает уменьшить дублирование кода
- Расширяемость кода – CBV может быть расширен, чтобы включить больше функций с помощью миксинов
- Структурирование кода – В CBV Представление на основе классов помогает отвечать на различные http-запросы с помощью различных методов экземпляра класса вместо условных операторов ветвления внутри одного представления на основе функций.
Представление на основе классов Django предоставляет метод экземпляра класса as_view ()
, который служит точкой входа для любого универсального CBV. Распознаватель URL-адресов Django ожидает отправки запроса, переданного через него, вызываемому объекту(функции). Метод экземпляра класса as_view()
в каждом универсальном представлении создает крючок для вызова класса так же, как и метод. Таким образом, конфигурация URL-адреса для вызова CBV следует приведенному ниже шаблону.
urlpatterns = [ url(r'^homepage/', ClassView.as_view(), name = "url_name") ]
Затем метод as_view()
вызывает метод dispatch ()
, который, в свою очередь, вызывает метод экземпляра класса, определенный для применимого метода http-запроса, если он доступен, или создает исключение HttpResponseNotAllowed
.
CBV.as_view() ------> CBV.dispatch() -------------------- | | | | and so on. v v v v get post head put
Атрибуты базового класса могут быть переопределены в дочернем классе, как и в стандартном подходе Python. В качестве альтернативы новый атрибут может быть передан в качестве аргумента методу as_view()
CBV
Пример: В базовом классе у нас есть
class BaseClass(View): greetings = "Good morning" def get(self, request): return HttpResponse(greetings) class ChildClass(View): greetings = "Good afternoon" def get(self, request): return HttpResponse(greetings)
Это также можно сделать в конфигурации URL-адреса, как показано ниже,
urlpatterns = [ url(r'^homepage/', ChildClass.as_view(overriden_attrbute = "new value"), name = "url_name") ]
В принципе, django CBV наследуется от общего класса представления. Однако CBV может наследовать от любого из доступных общих представлений. NB: CBV может иметь только одно родительское общее родительское представление, его функциональность также может быть улучшена за счет использования миксинов.
Использование Миксинов
Одним из преимуществ использования представления на основе классов является его расширяемость, это качество дополнительно повышается за счет использования миксинов. Миксины-это форма множественного наследования, которая позволяет сочетать поведение нескольких родительских классов.Они используются для добавления дополнительных функций и поведения в классы. Миксины предназначены для наследования, а не для прямой реализации. В CBVs миксины передаются в качестве крайнего левого аргумента, в то время как классы общего представления Django размещаются справа. Стоит отметить,что расширение представления класса с несколькими миксинами может привести к некоторому неожиданному поведению, затруднит чтение дочернего класса, чтобы узнать, что он делает, и тем труднее будет узнать, какой метод из какого Миксина переопределить. Однако при осторожном использовании миксины являются отличными инструментами для добавления надежных функциональных возможностей в CBV. см.Пример ниже.;
class NewMixin(object): def do_whatever(self, *args, **kwargs): #do whatever
Вышеуказанное смешивание используется, как показано ниже
from django.views.generic import TemplateView class FreshViewClass(NewMixin, TemplateView): def do_something_awesome(self): continue here
Методы, определенные в микшировании, могут быть вызваны непосредственно в классе Fresh View
.
Обработка форм с помощью CBV
В отличие от представлений на основе функций,где методы http оцениваются в операторах условного ветвления, представления на основе классов обрабатывают каждый тип запроса в отдельном методе экземпляра класса, названном соответственно методу запроса.Например, метод get()
обрабатывает запрос GET, а метод post()
обрабатывает запросы POST.
from django.http import HttpResponseRedirect from django.shortcuts import render from django.views.generic import View from .forms import MyForm class MyFormView(View): form_class = MyForm initial = {'key': 'value'} template_name = 'form_template.html' def get(self, request, *args, **kwargs): form = self.form_class(initial=self.initial) return render(request, self.template_name, {'form': form}) def post(self, request, *args, **kwargs): form = self.form_class(request.POST) if form.is_valid(): #return HttpResponseRedirect('/success/') return render(request, self.template_name, {'form': form})
Этот класс можно легко расширить, настроив атрибуты класса, такие как шаблон и класс form_class, в другом классе, который его наследует.
Использование Декораторов В Представлениях На Основе Классов
Декораторы могут быть переданы CBV, используя любой из этих 3 подходов. I. В конфигурациях URL-адресов этот подход используется для применения декораторов на основе каждого экземпляра.
from django.contrib.auth.decorators import login_required, permission_required from django.views.generic import TemplateView from .views import MyViewClass urlpatterns = [ url(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))), url(r'^vote/', permission_required('polls.can_vote')(MyViewClass.as_view())),]
II. Украшение класса dispatch()
метод | as_view () , который передается в URL CBV, вызывает метод
dispatch () класса представления, который, в свою очередь, вызывает соответствующий метод http-запроса. По сути, метод
dispatch() можно рассматривать как основную точку входа любого CBV, и поэтому имеет смысл поместить здесь наших декораторов. Для этого оболочка
@method_decorator() используется для преобразования декоратора представления в декоратор метода. Это связано с тем, что метод класса не совсем совпадает с функцией, поэтому декораторы функций не могут использоваться непосредственно на
class methods. @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(ProtectedView, self).dispatch(*args, **kwargs)
Несколько общих декораторов могут быть переданы в списке или кортеже и вызваны одновременно внутри оболочки @method_decorator ()
.
decorators = ['permission 1','permission2'...] @method_decorator(decorators) def dispatch(self, *args, **kwargs): return super(ProtectedView, self).dispatch(*args, **kwargs)
III. Украсьте класс и передайте имя метода, который будет украшен, например
@method_decorator(login_required, name='dispatch') class ProtectedView(TemplateView): template_name = 'secret.html'
Для сгруппированных общих общих декораторов
decorators = ['permission 1','permission2'...] @method_decorator(decorators, name='method_name') def dispatch(self, *args, **kwargs): return super(ProtectedView, self).dispatch(*args, **kwargs)
Несколько декораторов также могут быть переданы в CBV, как показано ниже
@method_decorator(never_cache, name='dispatch') @method_decorator(login_required, name='dispatch') class ProtectedView(TemplateView): template_name = 'secret.html'
Итак, в своем следующем проекте Djangoproject попытайтесь исследовать доброту CBV. Ты будешь рад, что сделал это. Счастливого кодирования !