Комментарии 22
Удобно, когда нужно описать джва десятка почти одинаковых views. Еще я полюбил разделение HTTP GET / POST / DELETE в разные методы (еще до включения этой штуки в транк у меня был похожий фрагмент кода, реализующий именно это).
С другой стороны, использовать class-based views повсеместно, на мой взгляд, оверкилл. Функции проще и прозрачнее классов, их легче читать и отлаживать.
С другой стороны, использовать class-based views повсеместно, на мой взгляд, оверкилл. Функции проще и прозрачнее классов, их легче читать и отлаживать.
+3
Ну а зачем, «плодить» похожие функции, если в них меняется только одно действие, обработка формы к примеру.
Да и отладить проще маленький метод, нежели вчитываться в большую функцию.
Да и отладить проще маленький метод, нежели вчитываться в большую функцию.
0
С помощью class-based вы можете разбить выполнение вьюхи на логические блоки общие для всего проекта, разложив их по методам класса. Это позволяет очень удобно расширять функциональность в дочерних классах, используя super() и прочие прелести. Мixins опять же.
Да, придумать изящную архитектуру будет немного сложнее, но в случае успеха читаться это будет гораздо лучше функциональной простыни.
Да, придумать изящную архитектуру будет немного сложнее, но в случае успеха читаться это будет гораздо лучше функциональной простыни.
0
А как именно вы рассовали get/post в разные методы?
А то вот я привык уже к такому по gae, а как соорудить в джанге что-то не соображу.
А то вот я привык уже к такому по gae, а как соорудить в джанге что-то не соображу.
0
gist.github.com/1688557 вот такая штука, и от нее наследуется view.
0
get_context разве не должна возвращать context?
0
1. Если метод нужно реализовывать в классе-наследнике, то нужно не `pass`, а `raise NotImplementedError`
2. Если вам нужно что-то сделать с queryset'ом, то это лучше делать в менеджере модели, а не во вьюхе.
3. Сериализация (в том числе и в JSON) уже есть в Джанге.
А еще смотрите, если вы решите использовать ваше `MixedView` для другой модели, то, вам придется написать:
Восклицательными знаками я отметил строчки, которые придется копировать без изменений. Их 6 из 10! Просто anti-DRY. Можно, в качестве альтернативы, добавить еще один слой наследования и в конец запутать код.
Мне кажется, что CBV в 95% случаев не нужны. Хитросплетения методов и цепочек наследования намного сложнее поддерживать, чем функции. Они не гибкие (если вы используете ListView, а однажды вам понадобится вывести не один а два списка чего-то, что тогда?). Если у вас реально сложная иерархия вьюх в проекте, то может быть CBV и подойдут, но много ли таких проектов.
2. Если вам нужно что-то сделать с queryset'ом, то это лучше делать в менеджере модели, а не во вьюхе.
3. Сериализация (в том числе и в JSON) уже есть в Джанге.
А еще смотрите, если вы решите использовать ваше `MixedView` для другой модели, то, вам придется написать:
class ArticleView(MixedView):
def get_context(self, request): #!
context = dict() #!
context['articles'] =Article.objects.all()
return context #!
template_name = 'articles_list.html'
def convert_context_to_json(self, context): #!
json_context = dict() #!
json_context['article_names'] = [p.name for p in context['articles']]
return json.dumps(json_context, encoding='utf-8', ensure_ascii=False) #!
Восклицательными знаками я отметил строчки, которые придется копировать без изменений. Их 6 из 10! Просто anti-DRY. Можно, в качестве альтернативы, добавить еще один слой наследования и в конец запутать код.
Мне кажется, что CBV в 95% случаев не нужны. Хитросплетения методов и цепочек наследования намного сложнее поддерживать, чем функции. Они не гибкие (если вы используете ListView, а однажды вам понадобится вывести не один а два списка чего-то, что тогда?). Если у вас реально сложная иерархия вьюх в проекте, то может быть CBV и подойдут, но много ли таких проектов.
+9
Под «что-то делать с queryset-ом» вы имели ввиду
Как это грамотно прикрутить к менеджеру модели?
[p.name for p in context['items']]
?Как это грамотно прикрутить к менеджеру модели?
0
Примерно так:
Ну и затем вызывать
from django.core import serializers
class MyModelManager(models.Manager):
def to_json(self):
return serializers.serialize('json', self.all(), fields=('name',), ensure_ascii=False)
class MyModel(models.Model):
# всякие поля тут
# ...
objects = MyModelManager()
Ну и затем вызывать
MyModel.objects.to_json()
.+2
За 1 и 3 большое спасибо, а 2 не понял. Какие именно действия с QuerySet'ом тут нужно перенести в менеджер? Это ведь нужно делать, если предполагается еще где-то использовать такой запрос?
> Если у вас реально сложная иерархия вьюх в проекте, то может быть CBV и подойдут, но много ли таких проектов.
Дело быть не только в сложной иерархии вьюх в одном проекте, но и в их использовании в других проектах. Хочется, чтобы код, написанный для одного проекта, был бы полезен в других. Это такой межпроектный DRY. Понятно, что создавая лишний уровень абстракции использованием наследования мы усложняем отладку и общее понимание кода, однако мы же выигрываем в астрагировании — программист пишущий MixedView, например, не должен будет задумываться о том, что и как сериализуется.
Мне нравится идея выделения отдельной части представления, ответственной за конечное преобразование данных в ответ. Потому что компоновка данных из базы, их предобработка по запросу — это отдельная задача, а преобразование запроса для просмотра в том или ином виде — совсем другая. И, как Вы подсказали, задача сериализации подготовленных для ответа данных в JSON, например, решается одинаково, независимо от вида этих данных.
> Если у вас реально сложная иерархия вьюх в проекте, то может быть CBV и подойдут, но много ли таких проектов.
Дело быть не только в сложной иерархии вьюх в одном проекте, но и в их использовании в других проектах. Хочется, чтобы код, написанный для одного проекта, был бы полезен в других. Это такой межпроектный DRY. Понятно, что создавая лишний уровень абстракции использованием наследования мы усложняем отладку и общее понимание кода, однако мы же выигрываем в астрагировании — программист пишущий MixedView, например, не должен будет задумываться о том, что и как сериализуется.
Мне нравится идея выделения отдельной части представления, ответственной за конечное преобразование данных в ответ. Потому что компоновка данных из базы, их предобработка по запросу — это отдельная задача, а преобразование запроса для просмотра в том или ином виде — совсем другая. И, как Вы подсказали, задача сериализации подготовленных для ответа данных в JSON, например, решается одинаково, независимо от вида этих данных.
0
По поводу 2, тут, скорее, дело вкуса (поэтому «лучше», а не «нужно» :-)), но во view этому коду точно не место. Можно в менеджер, можно в отдельный сериализатор. Даже если его предполагается использовать один раз, есть и другие причины. Например, чтобы протестировать, как работает сериализация, вам нужно «прогнать» view полностью, с контекстом, реквестом и прочим. Если вынести его куда-нибудь, тестирование становится приятным. Документировать код проще, глядя на менеджер, я сразу вижу, что он сериализуется в json, тут логика не так ясна. Сильное связывание опять же, получается, что я не могу сериализовать объект без атрибута
Плюс менеджеры не менее «реюзабельны», чем CBV, тот самый межпроектный DRY.
> Мне нравится идея выделения отдельной части представления, ответственной за конечное преобразование данных в ответ.
В вашем случае это
name
.Плюс менеджеры не менее «реюзабельны», чем CBV, тот самый межпроектный DRY.
> Мне нравится идея выделения отдельной части представления, ответственной за конечное преобразование данных в ответ.
В вашем случае это
HttpResponse(data, content_type='application/json')
. Если очень необходимо это выделить, то почему бы не так?0
context=super(MyClassView, self).get_context_data() вместо context=dict() не лучше ли?
0
CBV хороши для приложений, которые делаются для повторного использования. Сколько раз сталкивался: есть некое приложение, в нем вьюха, и хочется немного изменить ее поведение. И вот тут вьюхи на функциях предстают как черный ящик — на входе параметры, на выходе — HttpResponse, с которым уже мало что можно сделать. Хорошо, если автор предусмотрел какие-то параметры, с помощью которых можно кастомизировать поведению вьюхи. Иначе остается только переписывать весь ее код ради небольших изменений
+2
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Class-based views — зачем и как использовать