Я только начал работать с Django, пришедшим из лет Spring MVC, и реализация форм выглядит немного сумасшедшей. Если вы не знакомы, формы Django начинаются с класса модели формы, который определяет ваши поля. Spring также начинается с объекта поддержки формы. Но там, где Spring предоставляет taglib для привязки элементов формы к базовому объекту в вашем JSP, Django имеет виджеты форм, привязанные непосредственно к модели. Существуют виджеты по умолчанию, в которых вы можете добавить атрибуты стиля к своим полям, чтобы применять CSS или определять полностью настраиваемые виджеты как новые классы. Все это идет в вашем коде Python. Это кажется мне чокнутым. Во-первых, вы помещаете информацию о своем представлении непосредственно в вашу модель, а во-вторых, вы связываете свою модель с конкретным представлением. Я что-то пропустил?
РЕДАКТИРОВАТЬ: Пример кода в соответствии с просьбой.
Джанго:
# Class defines the data associated with this form
class CommentForm(forms.Form):
# name is CharField and the argument tells Django to use a <input type="text">
# and add the CSS class "special" as an attribute. The kind of thing that should
# go in a template
name = forms.CharField(
widget=forms.TextInput(attrs={'class':'special'}))
url = forms.URLField()
# Again, comment is <input type="text" size="40" /> even though input box size
# is a visual design constraint and not tied to the data model
comment = forms.CharField(
widget=forms.TextInput(attrs={'size':'40'}))
Spring MVC:
public class User {
// Form class in this case is a POJO, passed to the template in the controller
private String firstName;
private String lastName;
get/setWhatever() {}
}
<!-- JSP code references an instance of type User with custom tags -->
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- "user" is the name assigned to a User instance -->
<form:form commandName="user">
<table>
<tr>
<td>First Name:</td>
<!-- "path" attribute sets the name field and binds to object on backend -->
<td><form:input path="firstName" class="special" /></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName" size="40" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes" />
</td>
</tr>
</table>
</form:form>
Ответы:
Да, формы Django - беспорядок с точки зрения MVC, предположим, вы работаете в большой игре супергероев MMO и создаете модель Hero:
Теперь вас попросят создать для него форму, чтобы игроки ММО могли вводить суперсилы своего героя:
Поскольку Shark Repellent является очень мощным оружием, ваш босс попросил вас ограничить его. Если у героя есть Репеллент Акулы, он не может летать. Большинство людей просто добавляют это бизнес-правило в чистую форму и называют его днем:
Этот шаблон выглядит круто и может работать в небольших проектах, но, по моему опыту, его очень сложно поддерживать в больших проектах с несколькими разработчиками. Проблема в том, что форма является частью представления MVC. Таким образом, вам придется помнить это бизнес-правило каждый раз, когда вы:
Суть в том, что файл forms.py полностью посвящен макету формы и представлению, вам никогда не следует добавлять бизнес-логику в этот файл, если вам не нравится возиться со спагетти-кодом.
Лучший способ справиться с проблемой героя - использовать метод очистки модели и специальный сигнал. Очистка модели работает так же, как очистка формы, но она сохраняется в самой модели: при очистке HeroForm автоматически вызывается метод очистки Hero. Это хорошая практика, потому что если другой разработчик напишет другую форму для Героя, он получит бесплатную проверку репеллента / мухи.
Проблема с чистым заключается в том, что он вызывается только тогда, когда модель изменяется формой. Он не вызывается, когда вы сохраняете его вручную (), и вы можете получить недопустимого героя в вашей базе данных. Чтобы противостоять этой проблеме, вы можете добавить этот слушатель в свой проект:
Это вызовет метод clean при каждом вызове save () для всех ваших моделей.
источник
Вы смешиваете весь стек, есть несколько слоев:
Модель Джанго определяет структуру данных.
Форма Django - это ярлык для определения форм HTML, проверки полей и перевода значений Python / HTML. Это не строго необходимо, но часто удобно.
Django ModelForm - это еще один ярлык, короче говоря, подкласс Form, который получает свои поля из определения модели. Просто удобный способ для общего случая, когда форма используется для ввода данных в базу данных.
и наконец:
Некоторые люди считают это ересью; но важно помнить, что MVC изначально был определен для приложений с графическим интерфейсом, и это довольно неудобно для веб-приложений.
источник
Я отвечаю на этот старый вопрос, потому что другие ответы, кажется, избегают конкретной упомянутой проблемы.
Формы Django позволяют легко написать небольшой код и создать форму со стандартными настройками. Любая настройка очень быстро приводит к «большему количеству кода» и «большему количеству работы» и несколько сводит на нет основное преимущество системы форм.
Библиотеки шаблонов, такие как django-widget-tweaks значительно упрощают настройку форм. Надеемся, что подобная настройка на месте, в конце концов, будет легкой с простой установкой Django.
Ваш пример с django-widget-tweaks:
источник
(Я использовал курсив для обозначения концепций MVC, чтобы сделать это более разборчивым.)
Нет, на мой взгляд, они не ломают MVC. Работая с Django Models / Forms, думайте об этом как об использовании всего стека MVC в качестве Модели :
django.db.models.Model
является базовой моделью (содержит данные и бизнес-логику).django.forms.ModelForm
обеспечивает контроллер для взаимодействия сdjango.db.models.Model
.django.forms.Form
(как обеспечивается через наследованиеdjango.forms.ModelForm
) - это представление, с которым вы взаимодействуете.ModelForm
этоForm
, так что эти два слоя тесно связаны между собой . По моему мнению, это было сделано для краткости в нашем коде и для повторного использования кода в коде разработчиков Django.Таким образом
django.forms.ModelForm
(со своими данными и бизнес-логикой) становится сама Модель . Вы можете ссылаться на него как (MVC) VC, который является довольно распространенной реализацией в ООП.Взять, к примеру,
django.db.models.Model
класс Джанго . Когда мы смотрим наdjango.db.models.Model
объекты, мы видим Model, хотя это уже полная реализация MVC. Предполагая, что MySQL является внутренней базой данных:MySQLdb
является модель (слой хранения данных и бизнес - логики относительно того, как взаимодействовать с / проверки достоверности данных).django.db.models.query
является контроллером (обрабатывает ввод из представления и переводит его для модели ).django.db.models.Model
это представление (с которым взаимодействует пользователь).Это взаимодействие аналогично вашим «разработчикам на стороне клиента» при работе с
yourproject.forms.YourForm
(наследованиемdjango.forms.ModelForm
) от объектов:django.db.models.Model
, им нужно знать, как взаимодействоватьyourproject.forms.YourForm
(их модель ).MySQLdb
, ваши «разработчики на стороне клиента» не должны ничего знать оyourproject.models.YourModel
.источник