2009-12-15 5 views
6

Je me demande comment créer au mieux des pages HTML dans Django qui peuvent être utilisées pour afficher ou éditer des données. C'est-à-dire que j'aimerais que les valeurs du champ apparaissent sous forme de texte en mode affichage, mais dans leurs widgets en mode édition/ajout. Il semble que Django n'ait pas été conçu pour cela: les champs apparaissent toujours dans leurs widgets (par exemple, saisie de texte, zone de texte, etc.).Utiliser les formulaires Django pour afficher et éditer?

Existe-t-il une technique courante pour gérer cela, à moins d'utiliser des formulaires pour l'un et pas pour l'autre?

Je pensais à un filtre templatetag personnalisé qui pourrait être utilisé pour chaque champ de formulaire, comme:

{{form.field_name | render_field: Mode}}

où render_field serait soit revenir HTML du champ widget, ou juste la valeur en tant que texte, basé sur le mode.

Ai-je manqué quelque chose, ou est-ce une solution viable?

Répondre

3

Répondre à ma propre question, apparemment. J'ai fini avec une solution en trois parties:

  1. fixer le modèle à la forme, donc je vais avoir les widgets d'affichage par défaut pour chaque champ
  2. écrire le formulaire en utilisant une étiquette de modèle, il passe sous la forme .field, l'utilisateur et l'action
  3. écrire une étiquette de modèle pour gérer rendre # 2

Première étape:

 
form.model = Model(...) 

Deuxième étape:

 

{{form.field1.label}} 
{% render form.field1 user action %} 


{{form.field2.label}} 
{% render form.field2 user action %} 

Troisième étape:

Quelque chose comme:

 
def render(formfield, user, action, default_text="Private"): 
    if not user.is_authenticated(): 
     action = "view" 
    if action == "view": 
     if user.is_authenticated(): 
      fieldname = formfield.name 
      retval = str(getattr(formfield.form.model, fieldname)) 
     else: 
      retval = default_text 
    else: 
     retval = formfield.as_widget() 
    return retval 
0

Puisque vous enregistrez les données, vous devez avoir un modèle attaché au formulaire en quelque sorte, un modèle ou non. Donc, vous pouvez simplement utiliser ce modèle directement pour obtenir les valeurs et le rendre dans un modèle comme vous le souhaitez. La suggestion ci-dessus serait possible, mais étant donné que les formulaires peuvent être plutôt complexes, ce n'est probablement pas une tâche facile ou vaut la peine. Cela dépend de combien de fois vous voulez faire cela. Mais alors il serait probablement plus facile de créer un filtre pour le modèle au lieu du formulaire.

+0

Oui, je peux utiliser le modèle, mais cela ne profite pas de quoi que ce soit que les formes peuvent faire. Qu'est-ce qu'un filtre doit faire avec cela? J'ai beaucoup d'affichages/éditer des vues, donc un bon choix pourrait nous éviter d'avoir à faire chacun deux fois (une fois pour l'affichage, une fois pour l'édition). –

0

dans un modèle principal font

{% if form %} 
    {% include 'form.html' %} 
{% else %} 
    {% include 'display.html' %} 
{% endif %} 

alors ces deux modèles serait juste la partie qui rend une forme ou une belle div organisée. De cette façon, la vue d'édition aurait un formulaire défini, et la vue d'affichage ne le ferait pas. Ce sera beaucoup plus facile à suivre que ce que vous essayez de faire (même si ce que vous essayez devrait être possible, je crois que votre méthode va souffrir de la performance). Je fais cela dans une application de blog de sorte que la page d'édition ressemble à la page d'affichage, ce qui rend extrêmement intuitif pour éditer/écrire des entrées de blog. (Sans parler de ce qui me permet de mettre très facilement certains ajax pour modifier les entrées dans aucune vue avec quelques jolis effets de fantaisie)

+0

C'est exactement ce que je ne veux pas faire. Je ne veux pas avoir deux formes, mais une. –

0

Ai-je raté quelque chose

Forms affiche non seulement les widgets sur le terrain, mais gérer également les données de poste. Un message envoyé l'obligerait à traiter le nettoyage des données, la gestion des erreurs de formulaire et de champ, etc.

Il s'agit d'une sorte de rupture du motif - pourquoi créer et rendre un objet formulaire uniquement pour le modifier pour qu'il ne ressemble pas à un formulaire?

Si vous êtes trop préoccupé par le travail sur les modèles, essayez de le résoudre avec l'héritage du modèle de la meilleure façon possible. Si vous êtes très sûr de vouloir changer uniquement la balise de champ, vous pouvez faire qqch comme

{% if form %} 
    {% for error in form.field.errors %} 
     {{ error|escape }} 
    {% endfor %} 
    {{ form.field }} 
{% else %} 
    {{ object.field }} 
{% endif %} 

pour tous les domaines, mais l'OMI qui n'est pas le point, YMMV. En outre, ce qui vient à l'esprit (en pensant à votre solution) consiste à attacher dynamiquement des widgets à des champs de formulaire, mais ce serait une sur-ingénierie.

0

J'ai le même problème. En ce moment j'ai des modèles séparés pour l'affichage et l'édition; le premier rend les champs d'objet, les derniers forment les champs (mais parfois aussi les objets, pour les objets qui ne sont pas éditables). La structure HTML peut être assez complexe: par exemple, sur certaines pages, j'ai de grandes tables représentant une hiérarchie d'objets à plusieurs niveaux. En conséquence, je me retrouve avec une grande quantité de code dupliqué dans les deux modèles, ce qui est le contraire de DRY.

J'ai déjà utilisé des filtres de gabarit avec des champs de formulaire pour enregistrer du code lors de l'affichage d'erreurs avec le champ. Je pense que ce serait une solution viable dans ce cas. Une autre possibilité consiste à utiliser une sous-classe ModelForm à laquelle il peut être demandé de rendre les versions non modifiables des champs. Cela aiderait à garder les modèles simples. Vous pouvez même afficher à la fois la version statique et la version modifiable d'un champ, et utiliser JavaScript pour basculer entre eux, en activant et en désactivant un mode d'édition.

Questions connexes