Найти - Пользователи
Полная версия: Подойдет ли django для проекта
Начало » Django » Подойдет ли django для проекта
1 2 3
barabansheg
Пишу один проект, потребовалось использовать ajax. Много функций во views.py возвращающих json массив. urls.py разростается все быстрее. 1 функция - 1 урл. Наверно проблема в том, что надо было использовать cbv, а я использую обычные функции. Есть ли смысл переписывать все это в cbv или лучше сразу смотреть в сторону node.js?
Lexander
Если план расширения закончен процентов на 60 и есть ресурсы, то еще не поздно перейти к CBV.
Учитывая фразу о Ноде, думаю, времени и ресурсов еще вагон :)
d1ffuz0r
а нода чем вам поможет?
kmike
Проекты все разные, и в такой постановке вопроса ответы неизбежно будут очень общие.

На node.js писать сложнее, чем на джанге, и кашу там сделать еще проще.

Мне кажется, лучше подумать о том, как организовать имеющийся код. Например, разделить все получше на приложения, унести больше логики в формы и менеджеры/кверисеты, выделить как-то логику сериализации, раз json много, или посмотреть на django-tastypie/django-rest-framework.

CBV магическим образом проблемы не решат, это всего лишь способ организации кода (imho неудачный). Мое личное мнение - проблем CBV только добавят, и что CBV (особенно generic views) - это ужас-ужас, который использовать не нужно никогда, но это уже лирика, и у других разработчиков может быть свое мнение по этому вопросу)
Lexander
kmike
CBV магическим образом проблемы не решат, это всего лишь способ организации кода (imho неудачный). Мое личное мнение - проблем CBV только добавят, и что CBV (особенно generic views) - это ужас-ужас, который использовать не нужно никогда, но это уже лирика, и у других разработчиков может быть свое мнение по этому вопросу)
А на чем основано ваше мнение?

Если что, мнение Сагалаева читал ;)
JOHN_16
barabansheg
может вы забыли про передачу аргументов из url в функцию представления? декораторы?

Таким образом можно организовать что бы urlconf выглядело как то так “^/json/(.*)” что бы часть урл передалась в 1 функцию представления, где уже реализовать необходимую логику которая бы возвращала нужный JSON ответ.
def foo(request, arg):
    if arg ...
    elif arg ...
    ...
    return response_with_json

я вот счаз пишу проект первый раз используя модель CBV ( но не джанговские,а самописанные), но пока не дошел до стадии что бы судить что лучше.
kmike
А на чем основано ваше мнение?

В Python часто приходят из других языков; я когда начинал писать на python, всюду классы тоже пытался засунуть (и в джанго-сайте вьюхи на классах делал тоже, по своему, CBV не было еще) - все оттого, что просто привык и не умел/боялся код без классов организовывать. Но ничего сложного в том, чтоб по-нормальному организовать все, не наворачивая классы, как оказалось, не было.

Мне не нравятся generic views на CBV, т.к. для того, чтоб понять, что происходит во вьюхе, нужно прочитать код нескольких миксинов и в голове построить, что в каком порядке выполняется (особенно если есть вызовы super()), с учетом MRO. С вьюхой на функциях “поток выполнения” читается сразу, а с классом он то “заныривает” куда-то во внутренности джанги, то “выныривает” оттуда.

Возьмем какой-нибудь ArchiveIndexView - если там что-то захочется поправить, нужно прочитать код MultipleObjectTemplateResponseMixin, BaseArchiveIndexView, BaseDateListView, DateMixin, MultipleObjectMixin (названия-то какие); понять, метод какого из классов будет в итоге вызываться с учетом MRO, в какой последовательности будет разворачиваться цепочка super-вызовов, найти метод, который лучше всего перекрыть, и переопределить его. Другими словами, думать об абстракциях и деталях реализации фреймворка вместо того, чтоб взять да написать необходимую логику.

Со временем, конечно, детали основных классов запомнятся, и будет вполне очевидно, какой метод нужно перекрыть - до тех пор, пока не начнешь поддерживать код другого разработчика, который надстроил свою иерархию классов. Или ладно, запомнили, какие методы и что где как работает в иерархии джанговских generic views (imho - мусорную информацию), уделили этому часть своего времени и сил - а выигрыш-то в чем? Кода-то больше получается.

Вот это разве не ад (пример из документации)?

class HybridDetailView(JSONResponseMixin, SingleObjectTemplateResponseMixin, BaseDetailView):
    def render_to_response(self, context):
        # Look for a 'format=json' GET argument
        if self.request.GET.get('format','html') == 'json':
            return JSONResponseMixin.render_to_response(self, context)
        else:
            return SingleObjectTemplateResponseMixin.render_to_response(self, context)

Решение с декоратором или наследником TemplateResponse будет по размеру короче (тут еще код JSONResponseMixin не приведен), при этом оно будет еще и более общим, его будет легче использовать повторно (ничего не будет завязано на конкретную иерархию - тут все привязывается к SingleObjectTemplateResponseMixin, например).

Ну вот например, топик сейчас в django-developers обсуждают: https://groups.google.com/forum/?fromgroups=#!topic/django-developers/7c7aI-slGNc

Вместо того, чтоб решить конкретную задачу и написать несложную логику в функции, CBV заставили в том топике людей решают какие-то странные проблемы, выискивать, какой бы метод переопределить среди всей иерархии (оказалось, что такого метода нет из-за того, в какой последовательности super вызывается). Предлагают добавить еще больше хуков в базовые классы (чтоб разбираться и читать это стало еще сложнее?).

Разница между подходами “вьюха на классах” и “вьюха на функциях” - примерно такая же, как “фреймворк” vs “библиотека”. Фреймворк вызывает ваш код (а вы дописываете какие-то штуки в заранее подготовленные места); вы вызываете код из библиотеки. Несмотря на то, что джангу фреймворком называют, она гораздо ближе к библиотеке, чем всякие symfony, и это замечательно.

Это все если не касаться холивара ООП vs ФП и тестирования.

Короче говоря, ничто не мешает по-нормальному организовать вьюхи на функциях, не пряча и не запутывая логику в дополнтельных абстракциях CBV.

Впрочем, сильно негативное отношение у меня к новым generic views только. Вполне допускаю, что сами по себе CBV могут быть полезными и удобными. Можно представить ситуацию, что вот есть какая-то библиотека, и она хочет предоставить возможность расширения своего функционала без изменения своего кода. Вот тут CBV (не generic) могут быть полезными, т.к. классы - это удобный инструмент в этой ситуации. Пользователь библиотеки может переопределил метод, чтоб тот делал чуть другое, подходящее к конкретной задаче. С функциями это тоже можно решить (передав коллбэк), но классы к этому синтаксический сахар предоставляют в виде наследования, они удобнее и привычнее в этой ситуации.

Но в своем коде такая необходимость встречается достаточно редко: нет такого, что вот код и его нельзя трогать, и поэтому заранее позаботимся о том, чтоб можно было его не трогая какую-то задачу решить. Когда нужно - взял да поправил. Смысл в CBV редко когда есть, и уж точно (imho) не нужно их использовать “по умолчанию”, т.к. с ними (imho) код сложнее читать и править-улучшать, мыслительная нагрузка больше.
FishHook
ИМХО CBV - самая достойная вещь, которая есть в Django. Применять или не применять? Не нравятся Вам миксины и обобщенные представления - не используйте. В общем случае, чем отличается представление-класс от классического представления-функции?
# function
##
def foo(request, param):
    instance=get_object_or_404(MyModel, pk=param)
    return render_to_response('template.html', {'object':instance})
##
#class
##
class Foo(View):
    def get(self, request, *args, **kwargs):
        instance=get_object_or_404(MyModel, pk=self.kwargs['param'])
        return render_to_response('template.html', {'object':instance})

Пока CBV проигрывает, на одну строчку кода больше получилось. Но по сути, ничего страшного нет, код практически идентичный. Получается, что если Вам не нужны плюшки, предоставляемые обобщенными представлениями, то Вы вполне можете писать вьюхи-классы в том же стиле, в котором писали вьюхи-функции.
Сложнее пример
# function
##
def foo(request, param):
    instance=get_object_or_404(MyModel, pk=param)
    if request.method='POST':
        form=MyForm(request.POST)
            if form.is_valid:
                form.save()
                return HttpResponseRedirect(reverse( 'name' ))
            else:
                return render_to_response('template.html', {'object':instance, 'form':form})
    else:
        form=MyForm()
        return render_to_response('template.html', {'object':instance, 'form':form})
##
#class
##
class Foo(View):
    def get_instanse(self):
        instance=get_object_or_404(MyModel, pk=self.kwargs['param'])
        return instance
    def get(self, request, *args, **kwargs):
        form=MyForm()
        return render_to_response('template.html', {'object':self.get_instance(), 'form':form})
    def post(self, request, *args, **kwargs):
         form=MyForm(request.POST)
         if form.is_valid:
                form.save()
                return HttpResponseRedirect(reverse( 'name' ))
         else:
                return render_to_response('template.html', {'object':self.get_instance(), 'form':form})
Код опять получился больше, но он более структурирован и ИМХО легче читается. Однако никакого удобства от использования CBV пока не заметно, но и никакого “УЖАС-УЖАС” тоже нет. Выбор опять же за разработчиком. Если не напрягает в каждом представлении писать лесенки if.request, да бога ради. Меня напрягает. Конечно, если использовать дженерик, то класс становится совсем простым
class Foo(FormView):
    template_name='template.html'
    success_url= 'name'
    form_class=MyForm
    def get_context_data(self, **kwargs):
        context=super(Foo, self).get_context_data(**kwargs)
        context['object']=get_object_or_404(MyModel, pk=self.kwargs['param'])
        return context
Смущaет только get_context_data. Придется делать страшный миксин
class BaseParamView(objects):
    def get_context_data(self, **kwargs):
        context=super(BaseParametrView, self).get_context_data(**kwargs)
        context['object']=get_object_or_404(MyModel, pk=self.kwargs['param'])
        return context
И теперь
class Foo(BaseParamView, FormView):
    template_name='template.html'
    success_url= 'name'
    form_class=MyForm
class Bar(BaseParamView,FormView):
    template_name='another_template.html'
    success_url= 'another_name'
    form_class=MyAnotherForm
class Baz(BaseParamView, ListView)
    template_name='just_another_template.html'
    request=MyModel.objects.all()
    paginate_by=20

Резюмирую. Если в Django депрекнут классические представления-функции, то Вы по-прежнему сможете писать то же код, который писали. Если Вам не нравятся миксины, если Вам не нравятся обощенные представления, то Вас никто не заставляет их использовать в CBV. Пишите как писали.
Если используя CBV у Вас получается код, которого Вы сами боитесь, например появляется наследование семи миксинов, то стоит подумать о том, что Вы делаете что-то неправильно, а не сам CBV такой ужасный.

barabansheg
Насчет CBV подумал потому, что есть много однотипных функций где отличается лишь пара строк(используются разные модели, разные приложения, разные аргументы в зависимости от моделей). Если сводить подобное в одну функцию, то она разрастается до огромных размеров с кучей if-else.

Lexander, времени не то что бы вагон, но пока оно еще есть если переделывать. Но почитав примеры кода на node.js, понял, что лучше для меня будет даже оставить все как есть :)

JOHN_16, как-раз получится одна большая функция где много if-else, которые определяют что, куда и как сохранять.
JOHN_16
barabansheg
в таком случае вовсе не обязательно переводить весь код на CBV модель, достаточно сделать таковым код который бы выдавал JSON, раз вы говорите что
barabansheg
есть много однотипных функций где отличается лишь пара строк
, то тут так и напрашивается обобщенная функция или иерархия вызово функций/классов. Исходя из вашего проекта попробуйте - мне кажется много времени не займет, а решение может прояснится.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB