Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Стоит ли использовать формы Django (в частности виджеты)?

#python #python_3x #django #mvc


В Django довольно хорошо реализована работа с формами.
Основная их задача - это сохранение и валидация данных.

Но у них есть ещё много вкусняшек.
Самая значимая - это виджеты, которые позволяют указывать дополнительные атрибуты
к полям формы. В дальнейшем весь этот функционал позволяет вывести её на страницу одним
тегом {{ form }}



Вопрос в следующем:


  А стоит ли вообще использовать виджеты?


Задался я этим вопросом не случайно.
Начну свои размышления с того, что Django - MVC фреймворк. По всем заветам, при работе
с Django желательно отделять  мух от котлет модель, логику сайта и представление.

Но виджеты (как и некоторые другие особенности форм), по моему мнению, смешивают
логику сайта с представлением.

UPD: По большей степени я имею в виду указание классов и атрибутов, вроде placeholder,
для тегов через виджеты.



Удобно ли это?

Риторический вопрос. Смотря для кого.  

Если fullstack делать сайт-визитку, то да.
Но, как мне кажется, в больших командах это может затруднить взаимодействие с верстальщиком
или ответственным за шаблоны. Не думаю, что эти люди охотно полезут разбираться в forms.py.



Хотелось бы услышать Ваши мнения по этому вопросу, чтобы не допустить ошибку на этапе
архитектуры приложения и выработать паттерн работы с формами, если его ещё нет.

P. S.:
Я понимаю, что этот вопрос потенциально может породить некоторую дискуссию, но не
считаю, что ответы на него могут быть основаны только на мнении отвечающего. Призываю
в большей степени к оперированию существующими паттернами проектирования.
    


Ответы

Ответ 1



Стоит использовать виджеты. В основном стандартными. Нестандартные писать только если это действительно нужно и стандартные не подходят. Но виджеты (как и некоторые другие особенности форм), по моему мнению, смешивают логику сайта с представлением. Django - это фреймворк, в основе которого лежит MTV (Model Template View). V определено для «Представления» (View), слоя бизнес-логики. Этот слой содержит логику, как получать доступ к моделям и применять соответствующий шаблон. Вы можете рассматривать его как мост между моделями и шаблонами. Именно на этом слое происходит основаня работа с формами. Мы выбираем какая форма будет выводиться, как обрабатываться. Для удобства и поддержания порядка, формы выносят в forms.py файлы, а свои виджеты выносят в widgets.py (а иногда вся в куче). О виджетах Виджет – это представление поля в виде HTML кода. Виджеты обеспечивают генерацию HTML и извлечение соответствующих данных из GET/POST запросов. Это тоже логика, важно правильно извлекать данные из запросов и выводить правильное поле. Написать один раз и использовать везде, а не копипастить в templates проекта/приложения в каждой форме. Для примера возьмем поле FK, значения которого подгружаются по AJAX и выводят Подробную информацию об объекте, по причине схожести вариантов. Стандартными средствами django, сейчас это сделать нельзя, но написав после и widget, который будет выводить в атрибуте поля ссылку, откуда брать данные по AJAX, приведет FK поле в рабочий вид. Останется к форме прицепить js обработчик, который сделает остальную работу. UPD: По большей степени я имею в виду указание классов и атрибутов, вроде placeholder, для тегов через виджеты А где еще их выводить? Не в шаблоне же. Это атрибуты поля, а поле выводится через виджеты. А учитывая недавний вопрос про кастомный placeholder, переопределение шаблона стандартного поля очень даже удобное решение, чем строить костыли. Но, как мне кажется, в больших командах это может затруднить взаимодействие с верстальщиком или ответственным за шаблоны. Не думаю, что эти люди охотно полезут разбираться в forms.py. Верстальщик выдаст готовый html. Не нравится поле - переопределит его шаблон. А писать несколько форм с нестандартным представлением поля и копипастить - только заготовки проблем на будущие изменения. Я попробовал полностью перенести одну форму в forms.py и был немного обескуражен тем, что у меня получилось в итоге. Это заняло намного больше строк, чем я думал (в разы больше, чем в шаблоне). Но самое главное - это невероятно сильно замусорило чистый и элегантный Python код. Предлагаю Вам самим это оценить на примере указания placeholder А что мешает написать декоратор, который сам запихнет в них placeholder'ы ? Ну а если отличаются от label, то лучше в одной форме, чем в нескольких шаблонах. Так как паттерна я не нашёл (может его и вовсе нет), а мнения людей расплывчатые и сильно расходятся, может возникнуть ситуация с трудностями по поиску кода в проекте. Все разработчики должны без труда находить интересующие их участки кода, а если они потенциально могут находиться в разных файлах, то стоит избегать такую неопределённость. Трудностей нет. Интересующая форма -> Поле -> Виджет (стандартный или нет) -> Узнаем какой шаблон. Современные IDE (PyCharm) позволяют пройти этот путь зажав CTRL и тыкая на ЛКМ.

Ответ 2



Верстальщики и не должны интересоваться forms.py, это работа джанго-разработчика. В формах инкапсулируется работа с данными, точнее работа по вводу данных. Клиент же не должен их валидировать, так как в любом случае этим обязан заниматься сервер. Сервер должен их валидировать сам во-первых потому, что поступающие данные с клиента можно и подделать, а во-вторых клиент не должен знать как работает серверная часть. Если же в виджете будет определяться оформление форм и их стилистика, то это тоже ошибка, так как вы берёте на себя работу верстальщика. Пускай верстальщик сам определяет как будут располагаться поля и какого размера будут шрифты в своём коде, а не в коде джанги. В разработке есть два подхода: Если фронт разрабатывается одним проектом с бекендом, то фронтенщику достаточно знать шаблонизатор и дальше шаблонизатора им в бекенд лезть не следует. Заменить виджет, или написать нужный, может и сам джанго-разработчик, в конце-концов все джанго-разработчики - это веб-разработчики. Если же клиент разрабатывается отдельным приложением, то использовать формы особого смысла нет, работу с данными можно инкапсулировать в сериализаторах django-rest-framwork.

Ответ 3



Выслушав разные точки зрения, я пришёл к следующему промежуточному мнению: Виджеты использовать не стоит (UPD: почти) Аргументы: Не все вообще знают, что это такое :): Это довольно весомый аргумент, так как frontend-разработчик не интересуется. да и не должен интересоваться фреймворком Django со всеми вытекающими. Максимум, да и то не всегда - это знание шаблонизатора на уровне начинающего. Но моя печальная практика показывает, что некоторые просто забивают на это и перекладывают разработку шаблонов на backender'а, что ставит окончательную точку на идее познакомить frontender'а с формами. Трудность поддерживания: Если вёрстка находится и в forms.py, и в templates/ возникает необходимость поддерживать и связывать 2 файла вместо одного (что нарушает некоторые другие паттерны программирования). Это занимает больше человеко-часов, соответственно ухудшает производительность труда, требует больших экономических затрат и вот это вот всё со всеми вытекающими :) Трудность поиска: Так как паттерна я не нашёл (может его и вовсе нет), а мнения людей расплывчатые и сильно расходятся, может возникнуть ситуация с трудностями по поиску кода в проекте. Все разработчики должны без труда находить интересующие их участки кода, а если они потенциально могут находиться в разных файлах, то стоит избегать такую неопределённость. Неуклюжесть или же громоздкость: Я попробовал полностью перенести одну форму в forms.py и был немного обескуражен тем, что у меня получилось в итоге. Это заняло намного больше строк, чем я думал (в разы больше, чем в шаблоне). Но самое главное - это невероятно сильно замусорило чистый и элегантный Python код. Предлагаю Вам самим это оценить на примере указания placeholder: class RegisterForm(UserCreationForm): username = forms.CharField(required=True, widget=forms.TextInput(attrs={ 'placeholder': 'Логин', })) email = forms.EmailField(required=True, widget=forms.EmailInput(attrs={ 'placeholder': 'E-mail', })) password1 = forms.CharField(required=True, widget=forms.PasswordInput(attrs={ 'placeholder': 'Пароль', })) password2 = forms.CharField(required=True, widget=forms.PasswordInput(attrs={ 'placeholder': 'Повторите пароль', })) ... UPD: Я немного поменял точку зрения, относительно кода Выше, благодаря комментариям пользователя Мистер Фикс. В действительности, указывать placeholder в forms.py довольно хорошая идея, так как это касается логики формы. Верстальщик не должен делать предположений насчёт этого, ровно как и пользователь. Для меня этих доводов вполне хватило, чтобы отказаться от виджетов в пользу стандартной HTML разметки. Её все знают, при её редактировании не перезагружается сервер, а проблему структуризации решает шаблонизатор. Плюсов не так много, но они хотя бы есть по сравнению с формами. (UPD: Исключением является placeholder. Пересмотрев своё мнение, я пришёл к выводу о том, что он относится к логике формы и, пока нет другого способа указывать его, придётся использовать для этого виджеты.) P. S.: Я всё ещё жду Ваших комментариев и возможных решений. Буду рад услышать мнение каждого!

Комментариев нет:

Отправить комментарий