Acabo de comenzar a trabajar con Django después de años de Spring MVC y la implementación de formularios parece un poco loca. Si no está familiarizado, los formularios de Django comienzan con una clase de modelo de formulario que define sus campos. Spring comienza de manera similar con un objeto de respaldo de formulario. Pero donde Spring proporciona un taglib para vincular elementos de formulario al objeto de respaldo dentro de su JSP, Django tiene widgets de formulario vinculados directamente al modelo. Hay widgets predeterminados donde puede agregar atributos de estilo a sus campos para aplicar CSS o definir widgets completamente personalizados como nuevas clases. Todo va en tu código de Python. Eso me parece una locura. Primero, está poniendo información sobre su vista directamente en su modelo y, en segundo lugar, está vinculando su modelo a una vista específica. ¿Me estoy perdiendo de algo?
EDITAR: Algunos códigos de ejemplo según lo solicitado.
Django:
# 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>
Respuestas:
Sí, los formularios de Django son un desastre desde la perspectiva MVC, supongamos que estás trabajando en un gran juego de superhéroes MMO y estás creando el modelo Hero:
Ahora se le pide que cree un formulario para que los jugadores de MMO puedan ingresar sus superpoderes de héroe:
Como el repelente de tiburones es un arma muy poderosa, tu jefe te pidió que lo limitaras. Si un héroe tiene el Repelente de tiburones, entonces no puede volar. Lo que la mayoría de la gente hace es simplemente agregar esta regla de negocios en el formulario limpio y llamarlo un día:
Este patrón se ve genial y podría funcionar en proyectos pequeños, pero en mi experiencia esto es muy difícil de mantener en proyectos grandes con múltiples desarrolladores. El problema es que el formulario es parte de la vista del MVC. Por lo tanto, deberá recordar esa regla comercial cada vez que:
Mi punto aquí es que formularios.py tiene que ver con el diseño y la presentación del formulario, nunca debe agregar lógica de negocios en ese archivo a menos que disfrute de jugar con el código de espagueti.
La mejor manera de manejar el problema del héroe es usar el método de limpieza del modelo más una señal personalizada. La limpieza del modelo funciona como la limpieza de la forma, pero se almacena en el modelo mismo, cada vez que se limpia el HeroForm, se llama automáticamente al método de limpieza del héroe. Esta es una buena práctica porque si otro desarrollador escribe otro formulario para el Héroe, obtendrá la validación repelente / mosca de forma gratuita.
El problema con la limpieza es que solo se llama cuando un modelo es modificado por un formulario. No se llama cuando lo guarda () manualmente y puede terminar con un héroe no válido en su base de datos. Para contrarrestar este problema, puede agregar este oyente a su proyecto:
Esto llamará al método clean en cada llamada save () para todos sus modelos.
fuente
Estás mezclando toda la pila, hay varias capas involucradas:
Un modelo de Django define la estructura de datos.
un formulario Django es un acceso directo para definir formularios HTML, validaciones de campo y traducciones de valores Python / HTML. No es estrictamente necesario, pero a menudo es útil.
un Django ModelForm es otro acceso directo, en resumen, una subclase de Formulario que obtiene sus campos de una definición de Modelo. Solo una manera práctica para el caso común en el que se usa un formulario para ingresar datos en la base de datos.
y finalmente:
Algunas personas ven eso como herejía; pero es importante recordar que MVC se definió originalmente para aplicaciones GUI, y es un ajuste bastante incómodo para aplicaciones web.
fuente
Estoy respondiendo esta vieja pregunta porque las otras respuestas parecen evitar el problema específico mencionado.
Los formularios de Django le permiten escribir fácilmente código pequeño y crear un formulario con valores predeterminados razonables. Cualquier cantidad de personalización muy rápidamente conduce a "más código" y "más trabajo" y anula de alguna manera el beneficio principal del sistema de formularios
Las bibliotecas de plantillas como django-widget-tweaks facilitan mucho más la personalización de formularios. Con suerte, las personalizaciones de campo como esta eventualmente serán fáciles con una instalación vainilla de Django.
Su ejemplo con django-widget-tweaks:
fuente
(He usado cursiva para indicar los conceptos de MVC para hacer esto más legible).
No, en mi opinión, no rompen MVC. Cuando trabaje con modelos / formularios de Django, piense que utiliza una pila MVC completa como modelo :
django.db.models.Model
es el modelo base (contiene los datos y la lógica de negocios).django.forms.ModelForm
proporciona un controlador para interactuar condjango.db.models.Model
.django.forms.Form
(según lo dispuesto por herenciadjango.forms.ModelForm
) es la Vista con la que interactúa.ModelForm
es unForm
, por lo que las dos capas están estrechamente acopladas. En mi opinión, esto se hizo por brevedad en nuestro código, y para la reutilización del código dentro del código de los desarrolladores de Django.De esta manera,
django.forms.ModelForm
(con sus datos y lógica de negocios) se convierte en un Modelo en sí mismo. Puede hacer referencia a él como (MVC) VC, que es una implementación bastante común en OOP.Tomemos, por ejemplo, la
django.db.models.Model
clase de Django . Cuando miramos losdjango.db.models.Model
objetos, vemos el Modelo a pesar de que ya es una implementación completa de MVC. Suponiendo que MySQL es la base de datos de fondo:MySQLdb
es el Modelo (capa de almacenamiento de datos y lógica empresarial sobre cómo interactuar con / validar los datos).django.db.models.query
es el controlador (maneja la entrada de la vista y la traduce para el modelo ).django.db.models.Model
es la Vista (con lo que interactúa el usuario).Esta interacción es la misma que la de sus "desarrolladores del lado del cliente" cuando trabaja con
yourproject.forms.YourForm
(heredandodjango.forms.ModelForm
) objetos:django.db.models.Model
, ellos tendrían que saber cómo interactuar conyourproject.forms.YourForm
(su Modelo ).MySQLdb
, sus "desarrolladores del lado del cliente" no necesitan saber nada al respectoyourproject.models.YourModel
.fuente