Доброго времени суток, уважаемые читатели! Не так давно мной была опубликована первая часть статьи на данную тему. Я хочу еще раз поблагодарить всех пользователей, высказавших конструктивную критику, благодаря которой примеры в статье удалось привести к почти идеальному виду. В то же время я понял, что данный формат подачи материала является неэффективным: мы рассмотрели всего пару методов, реализованных в Class Based View (далее по тексту CBV). Во второй части я решил переработать подачу и далее постараюсь описать максимально возможное количество методов, представленных в API. Постараюсь, также, охватить те методы, которые были упущены в первой части. Очень надеюсь на конструктивную поддержку читателей и надеюсь, что и в дальнейшем у нас получится продуктивный диалог, в результате которого статья станет еще более информативной.
Часть 1, часть 2, часть 3, часть 4
dispatch
get_context_data
get_template_names
get_context_object_name
get
post
put
delete
head
options
trace
render_to_response
get_queryset
object
template_name
template_name_suffix
context_object_name
http_method_names
queryset
model
Для начала определимся, что такое вообще эти CBV, нужны ли они и где их стоит использовать. Наверное стоит подчеркнуть, что особого выбора нам разработчики Django не предоставляют. Скорее всего уже с 1.4 версии (судя по транку) generic views будут объявлены как deprecated, а в одной из следующих версий могут вообще отказаться от их использования. Поэтому я решил, как это часто бывает, не откладывать изучение в долгий ящик, а начать работу с CBV прямо сейчас. Собственно, за неимением подробной информации, данная статья и будет написана на личных наблюдениях.
Итак, CBV позволяет нам использовать особенности объектно-ориентированного программирования при разработке наших отображений. Теперь мы можем реализовывать базовые классы, несущие определенную функциональность и использовать их как примеси (mixins) для наших отображений.
Все отображения имеют точку входа, который можно считать и конструктором, это метод dispatch. Данный метод принимает аргумент request, являющийся экземпляром объекта HttpRequest, в качестве первого аргумента. В этом его основная схожесть с function based views. Также данный метод принимает все переданные отображению переменные в качестве именованных и неименованных позиционных аргументов (*args/**kwargs). Рассмотрим ��ару примеров работы с данным методом.
Метод dispatch является наилучшим местом, для использования декораторов. Для их указания необходимо использовать реализованный в django декоратор method_decorator. Допустим нам необходимо предоставить доступ к определенному списку объектов лишь для авторизованных пользователей:
Имейте ввиду, что метод dispatch для корректной работы должен возвращать ссылку на родительский диспетчер. В противном случае не произойдет корректной передачи управления.
Очень часто возникает необходимость передать нашему отображени дополнительный контекст. Допустим у нас есть статья, просмотр которой мы реализуем с помощью класса DetailView. Нам необходимо также получить список комментариев к данной статье. На мой взгляд метод get_context_data
будет лучшей точкой для реализации требуемого функционала.
Несколько забегая вперед уточню, что получить доступ к текущему объекту при реализации DetailView можно через атрибут object.
Если мы хотим узнать (или задать) имя для шаблона, который будет исп��льзовать наше отображение, то нам нужно обратить внимание на метод get_template_names. Данный метод возвращает список имен шаблонов, которые Django будет пытаться использовать в порядке их указания. По умолчанию наивысшим приоритетом будет обладать шаблон, указанный в атрибуте template_name нашего объекта. Если данный атрибут не указан, то Django будет пытаться использовать шаблон «название_приложения/имя_объекта_префикс». Например для приложения content и модели post данный путь будет иметь вид «content/post_префикс.html». Префикс задается с помощью атрибута template_name_suffix, либо используется префикс по умолчанию для данного типа отображения. Например для ListView префикс носит имя "_list", для DetailView "_detail". Если мы просто хотим, чтобы наше отображение использовало шаблон, который мы хотим, то нам достаточно лишь указать его с помощью атрибута template_name. Переопределение метода get_template_names может потребоваться, если нам необходимо собирать имя шаблона по своим правилам.
Часто бывает необходимо изменить имя переменной, под которой наш объект (или список объектов) доступен в шаблоне. Метод, отвечающий за данную функциональность носит имя get_context_object_name. Данный метод принимает в качестве аргумента объект (или список объектов). В случае с отдельным объектом имя переменной в шаблоне по умолчанию будет именем самого объекта. В случае со списком объектов это будет имя объекта с суффиксом _list. Например для объекта Post иимена переменных будут post и post_list для отдельного объекта и списка объектов соответственно. Мы можем явно указать имя переменной, если присвоим ее значение атрибуту context_object_name.
Представим, что перед нами стоит задача по реализации RESTful приложения, CBV предоставляет исчерпывающий набор методов для их реализации. Чтобы реализовать работу приложения через определенный метод, нам нужно лишь переопределить одноименный метод в нашем отображении. Список доступных методов: get, post, put, delete, head, options, trace. Работа с формами упрощается в разы, ведь мы можем использовать метод get для отображения нашей формы, а ее обработку перенести в метод post. Требуется добавить какой-либо дополнительный специфический http метод? Нет проблем, достаточно лишь допол��ить атрибут http_method_names, содержащий список имен доступных методов, а затем определить одноименный метод у себя в отображении. Все http методы должны возвращать объект HttpResponse. Если нам необходимо отрендерить шаблон нашего отображения, то мы можем для этого вызвать в вышеуказанных http методах метод render_to_response. Данный метод имеет не только такое же имя, как и его функциональный собрат, но и схожую функциональность.
Метод принимает в качестве аргумента требуемый контекст.
Прежде чем вывести информацию в шаблон нам необходимо ее получить. В этом нам поможет метод get_queryset, задача которого вернуть объект QuerySet. По умолчанию данный метод возвращает атрибут queryset если он определен, либо список всех объектов модели, которая указана в атрибуте model. Мы можем переопределить данный метод, чтобы он удовлетворял нашим задачам.
В данной части я постарался охватить по возможности все базовые (имеющиеся во всех типах CBV) методы. Если я что-то пропустил, то прошу сообщить и я дополню статью. Следующие части будут включать в себя описание особенностей отдельных типов CBV. Начну, пожалуй, с описания методов ListView и DetailView. Буду очень рад, если мои статьи помогут людям в поиске информации. Спасибо, что прочитали данную статью :)
Часть 1, часть 2, часть 3, часть 4
Ссылки для быстрого поиска методов
dispatch
get_context_data
get_template_names
get_context_object_name
get
post
put
delete
head
options
trace
render_to_response
get_queryset
Ссылки для быстрого поиска атрибутов
object
template_name
template_name_suffix
context_object_name
http_method_names
queryset
model
Общая информация
Для начала определимся, что такое вообще эти CBV, нужны ли они и где их стоит использовать. Наверное стоит подчеркнуть, что особого выбора нам разработчики Django не предоставляют. Скорее всего уже с 1.4 версии (судя по транку) generic views будут объявлены как deprecated, а в одной из следующих версий могут вообще отказаться от их использования. Поэтому я решил, как это часто бывает, не откладывать изучение в долгий ящик, а начать работу с CBV прямо сейчас. Собственно, за неимением подробной информации, данная статья и будет написана на личных наблюдениях.
Итак, CBV позволяет нам использовать особенности объектно-ориентированного программирования при разработке наших отображений. Теперь мы можем реализовывать базовые классы, несущие определенную функциональность и использовать их как примеси (mixins) для наших отображений.
Все отображения имеют точку входа, который можно считать и конструктором, это метод dispatch. Данный метод принимает аргумент request, являющийся экземпляром объекта HttpRequest, в качестве первого аргумента. В этом его основная схожесть с function based views. Также данный метод принимает все переданные отображению переменные в качестве именованных и неименованных позиционных аргументов (*args/**kwargs). Рассмотрим ��ару примеров работы с данным методом.
Метод dispatch является наилучшим местом, для использования декораторов. Для их указания необходимо использовать реализованный в django декоратор method_decorator. Допустим нам необходимо предоставить доступ к определенному списку объектов лишь для авторизованных пользователей:
from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator from django.views.generic import ListView class PostList(ListView): model = Post @method_decorator(login_required()) def dispatch(self, request, *args, **kwargs): return super(PostList, self).dispatch(request, *args, **kwargs)
Имейте ввиду, что метод dispatch для корректной работы должен возвращать ссылку на родительский диспетчер. В противном случае не произойдет корректной передачи управления.
Очень часто возникает необходимость передать нашему отображени дополнительный контекст. Допустим у нас есть статья, просмотр которой мы реализуем с помощью класса DetailView. Нам необходимо также получить список комментариев к данной статье. На мой взгляд метод get_context_data
будет лучшей точкой для реализации требуемого функционала.
from django.views.generic.detail import DetailView from models import Post, Comment class PostDetail(DetailView): model = Post def get_context_data(self, **kwargs): context = super(PostDetail, self).get_context_data(**kwargs) context['comments'] = Comment.objects.filter(post=self.object, is_delete=False).order_by('-created_at') return context
Несколько забегая вперед уточню, что получить доступ к текущему объекту при реализации DetailView можно через атрибут object.
Если мы хотим узнать (или задать) имя для шаблона, который будет исп��льзовать наше отображение, то нам нужно обратить внимание на метод get_template_names. Данный метод возвращает список имен шаблонов, которые Django будет пытаться использовать в порядке их указания. По умолчанию наивысшим приоритетом будет обладать шаблон, указанный в атрибуте template_name нашего объекта. Если данный атрибут не указан, то Django будет пытаться использовать шаблон «название_приложения/имя_объекта_префикс». Например для приложения content и модели post данный путь будет иметь вид «content/post_префикс.html». Префикс задается с помощью атрибута template_name_suffix, либо используется префикс по умолчанию для данного типа отображения. Например для ListView префикс носит имя "_list", для DetailView "_detail". Если мы просто хотим, чтобы наше отображение использовало шаблон, который мы хотим, то нам достаточно лишь указать его с помощью атрибута template_name. Переопределение метода get_template_names может потребоваться, если нам необходимо собирать имя шаблона по своим правилам.
Часто бывает необходимо изменить имя переменной, под которой наш объект (или список объектов) доступен в шаблоне. Метод, отвечающий за данную функциональность носит имя get_context_object_name. Данный метод принимает в качестве аргумента объект (или список объектов). В случае с отдельным объектом имя переменной в шаблоне по умолчанию будет именем самого объекта. В случае со списком объектов это будет имя объекта с суффиксом _list. Например для объекта Post иимена переменных будут post и post_list для отдельного объекта и списка объектов соответственно. Мы можем явно указать имя переменной, если присвоим ее значение атрибуту context_object_name.
Представим, что перед нами стоит задача по реализации RESTful приложения, CBV предоставляет исчерпывающий набор методов для их реализации. Чтобы реализовать работу приложения через определенный метод, нам нужно лишь переопределить одноименный метод в нашем отображении. Список доступных методов: get, post, put, delete, head, options, trace. Работа с формами упрощается в разы, ведь мы можем использовать метод get для отображения нашей формы, а ее обработку перенести в метод post. Требуется добавить какой-либо дополнительный специфический http метод? Нет проблем, достаточно лишь допол��ить атрибут http_method_names, содержащий список имен доступных методов, а затем определить одноименный метод у себя в отображении. Все http методы должны возвращать объект HttpResponse. Если нам необходимо отрендерить шаблон нашего отображения, то мы можем для этого вызвать в вышеуказанных http методах метод render_to_response. Данный метод имеет не только такое же имя, как и его функциональный собрат, но и схожую функциональность.
class PostDetail(DetailView): model = Post def get(self, request, **kwargs): return self.render_to_response(self.get_context_data(), **kwargs)
Метод принимает в качестве аргумента требуемый контекст.
Прежде чем вывести информацию в шаблон нам необходимо ее получить. В этом нам поможет метод get_queryset, задача которого вернуть объект QuerySet. По умолчанию данный метод возвращает атрибут queryset если он определен, либо список всех объектов модели, которая указана в атрибуте model. Мы можем переопределить данный метод, чтобы он удовлетворял нашим задачам.
class PostList(ListView): model = Post def get_queryset(self): qs = Post.objects.filter(is_delete=False).order_by('-created_at') if not self.request.user.is_authenticated(): return qs.exclude(is_private=True) return qs
В данной части я постарался охватить по возможности все базовые (имеющиеся во всех типах CBV) методы. Если я что-то пропустил, то прошу сообщить и я дополню статью. Следующие части будут включать в себя описание особенностей отдельных типов CBV. Начну, пожалуй, с описания методов ListView и DetailView. Буду очень рад, если мои статьи помогут людям в поиске информации. Спасибо, что прочитали данную статью :)
