Je viens de commencer à travailler avec Django après des années de Spring MVC et l'implémentation des formulaires semble être un peu folle. Si vous n'êtes pas familier, les formulaires Django commencent par une classe de modèle de formulaire qui définit vos champs. Spring commence également avec un objet de support de formulaire. Mais lorsque Spring fournit un taglib pour lier des éléments de formulaire à l'objet de support dans votre JSP, Django a des widgets de formulaire directement liés au modèle. Il existe des widgets par défaut où vous pouvez ajouter des attributs de style à vos champs pour appliquer du CSS ou définir des widgets entièrement personnalisés en tant que nouvelles classes. Tout va dans votre code python. Cela me semble dingue. Premièrement, vous mettez des informations sur votre vue directement dans votre modèle et deuxièmement, vous liez votre modèle à une vue spécifique. Suis-je en train de manquer quelque chose?
EDIT: Un exemple de code tel que demandé.
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>
Réponses:
Oui, les formulaires Django sont un gâchis du point de vue MVC, supposons que vous travaillez dans un grand jeu de super-héros MMO et que vous créez le modèle Hero:
Maintenant, vous êtes invité à créer un formulaire pour cela, afin que les joueurs MMO puissent entrer leurs super pouvoirs de héros:
Le Shark Repellent étant une arme très puissante, votre patron vous a demandé de la limiter. Si un héros possède le Shark Repellent, il ne peut pas voler. Ce que la plupart des gens font, c'est simplement d'ajouter cette règle commerciale sous la forme propre et de l'appeler un jour:
Ce modèle a l'air cool et pourrait fonctionner sur de petits projets, mais d'après mon expérience, il est très difficile à maintenir dans les grands projets avec plusieurs développeurs. Le problème est que le formulaire fait partie de la vue du MVC. Vous devrez donc vous souvenir de cette règle commerciale chaque fois que vous:
Mon point ici est que le forms.py concerne la mise en page et la présentation du formulaire, vous ne devez jamais ajouter de logique métier dans ce fichier, sauf si vous aimez jouer avec du code spaghetti.
La meilleure façon de gérer le problème des héros est d'utiliser la méthode de nettoyage de modèle plus un signal personnalisé. Le modèle propre fonctionne comme le formulaire propre mais il est stocké dans le modèle lui-même, chaque fois que HeroForm est nettoyé, il appelle automatiquement la méthode Hero propre. C'est une bonne pratique car si un autre développeur écrit un autre formulaire pour le héros, il obtiendra gratuitement la validation répulsif / anti-mouches.
Le problème avec le nettoyage est qu'il n'est appelé que lorsqu'un modèle est modifié par un formulaire. Il n'est pas appelé lorsque vous l'enregistrez manuellement () et vous pouvez vous retrouver avec un héros invalide dans votre base de données. Pour contrer ce problème, vous pouvez ajouter cet écouteur à votre projet:
Cela appellera la méthode propre à chaque appel save () pour tous vos modèles.
la source
Vous mélangez toute la pile, plusieurs couches sont impliquées:
un modèle Django définit la structure des données.
un formulaire Django est un raccourci pour définir des formulaires HTML, des validations de champs et des traductions de valeurs Python / HTML. Ce n'est pas strictement nécessaire, mais souvent pratique.
un Django ModelForm est un autre raccourci, en bref une sous-classe Form qui obtient ses champs à partir d'une définition de modèle. Juste un moyen pratique pour le cas commun où un formulaire est utilisé pour entrer des données dans la base de données.
et enfin:
Certaines personnes voient cela comme une hérésie; mais il est important de se rappeler que MVC a été défini à l'origine pour les applications GUI, et qu'il convient plutôt aux applications Web.
la source
Je réponds à cette vieille question parce que les autres réponses semblent éviter le problème spécifique mentionné.
Les formulaires Django vous permettent d'écrire facilement peu de code et de créer un formulaire avec des valeurs par défaut sensées. Toute personnalisation entraîne très rapidement «plus de code» et «plus de travail» et annule quelque peu le principal avantage du système de formulaire
Les bibliothèques de modèles comme django-widget-tweaks facilitent la personnalisation des formulaires. Espérons que les personnalisations sur le terrain comme celle-ci seront finalement faciles avec une installation Django vanille.
Votre exemple avec django-widget-tweaks:
la source
(J'ai utilisé l' italique pour signifier les concepts MVC pour le rendre plus lisible.)
Non, à mon avis, ils ne cassent pas MVC. Lorsque vous travaillez avec des modèles / formulaires Django, considérez-le comme utilisant une pile MVC entière comme modèle :
django.db.models.Model
est le modèle de base (contient les données et la logique métier).django.forms.ModelForm
fournit un contrôleur pour interagir avecdjango.db.models.Model
.django.forms.Form
(tel que fourni par héritage pardjango.forms.ModelForm
) est la vue avec laquelle vous interagissez.ModelForm
c'est unForm
, donc les deux couches sont étroitement couplées. À mon avis, cela a été fait pour la brièveté de notre code et pour la réutilisation du code dans le code des développeurs Django.De cette façon,
django.forms.ModelForm
(avec ses données et sa logique métier) devient un modèle lui-même. Vous pouvez le référencer en tant que (MVC) VC, qui est une implémentation assez courante dans la POO.Prenez, par exemple, la
django.db.models.Model
classe de Django . Lorsque nous regardons lesdjango.db.models.Model
objets, nous voyons le modèle même s'il s'agit déjà d'une implémentation complète de MVC. En supposant que MySQL est la base de données principale:MySQLdb
est le modèle (couche de stockage de données et logique métier concernant la manière d'interagir avec / valider les données).django.db.models.query
est le contrôleur (gère les entrées de la vue et les traduit pour le modèle ).django.db.models.Model
est la vue (avec laquelle l'utilisateur interagit).Cette interaction est la même que pour vos "développeurs côté client" lorsque vous travaillez avec
yourproject.forms.YourForm
(héritant dedjango.forms.ModelForm
) des objets:django.db.models.Model
, ils devraient savoir comment interagir avecyourproject.forms.YourForm
(leur modèle ).MySQLdb
, vos "développeurs côté client" n'ont besoin de rien savoiryourproject.models.YourModel
.la source