Как стать автором
Обновить

Комментарии 19

Продолжайте дальше :)
Хотелось бы увидеть что-нибудь с реализациями CreateView, и что-нибудь интересное с BaseDateListView.
Я лишь за :) В моих планах описать работу с CBV со всех сторон, причем на личном опыте. Уже готов пример статье работы с FormView (и будет опубликован в ближайшие дни).
Хотелось бы рассказать про основные SOAP модули (post/get/put/delete), и про остальные методы CBV. Тема достаточно интересная.
Давайте, публикуйте)
Хоть у этого блога и прилично читателей, но вот, к сожалению, реакции к статьям тут намного спокойнее, чем в других блогах. То есть, если «не выстрелит» — не отчаивайтесь.
Поправка, не SOAP конечно, а REST :)
Мне кажется, что за формирование кверисета get_queryset() должен отвечать. А он тут статичен, зато вся логика по его созданию и изменению в зависимости от условий размазывается в dispatch(), который суть точка входа и желательно его по возможности вообще не трогать.

По-моему, рабочая вьюха с минимальной функциональностью делается так:

class PostView(ListView):
    model = Post

Обратите внимание, никаких перекрытий dispatch() и прочего. Пагинацию тоже не надо использовать низкоуровнево: в ListView, примесью которого является MultipleObjectMixin, она (пагинация) работает по умолчанию (пруф и примеры)

Собственно, весь Ваш код можно переписать компактнее

class PostView(ListView):
    """
    Просмотр списка статей, доступных текущему пользователю
    """
    model = Post
    context_object_name = 'posts'
    template_name = 'posts.html'

    def queryset(self):
        qs = Post.objects.filter(is_delete=False).order_by('-created_at')

        if not request.user.is_authenticated():
            qs = qs.exclude(is_private=True)
        return qs

class PostsIndex(PaginatedList):
    """
    Список статей для главной страницы
    """
    def get_queryset(self):
        return super(PostsIndex, self).get_queryset().exclude(rating__lt=10)


Я не проверял, но мне кажется, что должно быть примерно так :)

А вообще, конечно, погорячились разработчики Джанги с обязательным введением CBV. Начнут ведь теперь лепить классы везде где надо и не надо
упс, сразу же работа над ошибками:

  1. в PostView следует читать queryset, а get_queryset
  2. в нём же: не request, а self.request
Ну вообще вы правы. Можно вообще все данные отображения свести до одного класса и реализовать классический RESTful. И насчет использования CBV это тоже холивар не для хабра) Просто в данной статье хотелось подчеркнуть особенности использования, показания лучшие стороны в ООП подобных отображений. То есть, что можно отнаследоваться от базового ListView и сделать свой класс с пагинацией, затем уже отнаследоваться от него и возвращать уже пагинованные списки объектов. Если делать все «по-человечески», то это можно реализовать в том числе «примесями (mixens)». ООП предлагает множество путей решения проблемы.
И да, везде использовать это не стоит, но иногда оправдано. Например, недавно решил переписать проект полностью на CBV, в итоге на логику отображений ушло намного меньше кода.
Можно вообще все данные отображения свести до одного класса и реализовать классический RESTful.

Мне кажется, вместо «можно» нужно употрелять слово «нужно». Собственно, они для того и писались.

Просто в данной статье хотелось подчеркнуть особенности использования, показания лучшие стороны в ООП подобных отображений

Самое грустное в том, что это неправильный пример. Я бы даже сказал — антипаттерн. Потому что (возможно, повторюсь):

  1. много буквстрок, следовательно «одним взглядом» весь код не охватить и не понять.
  2. написание собственного велосипеда вместо использования готового решения — это я в сторону пагинации. Вы на коленке реализовали то, что уже работает (и лучше :-)) из коробки.
  3. логика разбора кверисета находится совсем не там, где ей надлежит быть
  4. и таки да — перекрытие dispatch. Этого лучше по возможности избегать. Понятно, конечно, что далеко не всегда это пожелание осуществимо, но в данном случае — да.


Практическая полезность этого кода в том, что вы открыли dispatch — точку входа во вьюху. Молодым исследователям будет понятно, с чего начинать. Но я бы сделал приписку: «в чистом виде такой код к применению не рекомендуется» :-)
Насчет dispatch и get_queryset, в принципе, полностью согласен. Но пример не совсем удачный скорее не потому, что его можно сделать меньше, а потому, что он охватывает всего пару методов, имеющихся в CBV. В идеале, для лучшего восприятия материала, надо было показать работу и с остальными методами. Вот только не знаю как это лучше реализовать, чтобы все и сразу. А делать для этого отдельную статью было бы излишне с моей стороны.
Спасибо вам за конструктивные комментарии. Как я уже написал в статье — информации по CBV и правильным практикам их применения очень мало. Большинство их сходится лишь к холиварам на темы плохо это или хорошо. Поэтому все приходится изучать путем проб, ошибок и просмотра исходного кода. Пример в статье перепишу с учетом вашего комментария.
А в чем преимущество использования ООП во View?
Думаю то же, что и использование в других местах. Это не совсем преимущество, просто другой угол зрения, но для меня более удобным является возможность сделать базовый класс, определить функциональность, которая требуется в других отображениях. Затем данный класс можно наследовать другими отображениями как «примеси», используя на порядок меньше кода. Множественное наследование позволяет использовать несколько «примесей» для одного отображения, главное не забыть проконтролировать их порядок применения и конфликты.
Базовый класс т.н. абстрактный класс, я их так называю. Спасибо за статью, с нетерпением жду продолжения.
Базовый класс, абстрактный класс и примесь это понятия из разных граней ООП :)
UPD. Обновил пример в статье (спасибо пользователю marazmiki). А также выложил тестовый проект, включающий данный пример. Не забудьте отредактировать файл settings.py под свои нужды. Проект можно найти здесь. Если вы обнаружите какие-либо ошибки или недоработки, то прошу сообщить.
*(а я кланяюсь, кланяюсь)*

class Posts(ListView, MultipleObjectMixin):


Не надо наследоваться от MultipleObjectMixin: ListView уже сделал это за Вас.
И снова от меня тысяча благодарностей :) Действительно, я даже не удосужился посмотреть в исходный код. Радует, что разработчики django предусмотрели в списке объектов пагинацию «из коробки». Однако огорчает обилие лишних переменных. Все эти object_list и page_obj стоило, наверное, как-то собрать в 1 объект, чтобы было проще вызывать в шаблоне.
После обновления примера объяснение к нему больше не соответствует коду, надо бы тоже поправить. Ну и import MultipleObjectMixin
теперь можно убрать.
Да уж скорее бы :) Чувствовал себя идиотом, пока не дошло что код не тот. Ну или по крайней мере UPD подвиньте повыше, читатель пока до него не дойдет будет сидеть с круглыми глазами.
Вроде исправил) Прошу прощения, что сразу не заметил новые комментарии, по какой-то причине слетела подписка на статью, обнаружил чисто случайно.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации