Django formes, l'héritage et l'ordre des champs de formulaire
Je suis en utilisant Django formes dans mon site web et souhaitez contrôler l'ordre des champs.
Voici comment je définis mes formulaires:
class edit_form(forms.Form):
summary = forms.CharField()
description = forms.CharField(widget=forms.TextArea)
class create_form(edit_form):
name = forms.CharField()
Le nom est immuable et ne doivent être énumérées lorsque l'entité est créée. J'ai utiliser l'héritage pour ajouter de la cohérence et de la SEC principes. Ce qui se passe qui n'est pas fausse, en fait totalement prévu, c'est que le champ nom de la liste dans la vue/html, mais je voudrais le nom de domaine pour être au top de résumé et une description. Je me rends compte que je pouvais facilement le fixer en copiant le résumé et la description dans create_form et de perdre l'héritage, mais j'aimerais savoir si cela est possible.
Pourquoi? Imaginez que vous avez 100 champs dans edit_form et ont pour ajouter 10 les champs de la table dans create_form - la copie et le maintien de ces deux formes ne serait pas l'air si sexy alors. (C'est pas mon cas, je suis juste un exemple)
Alors, comment puis-je remplacer ce comportement?
Edit:
Apparemment il n'y a pas de bonne façon de le faire sans passer par le méchant hacks (tripoter .champ d'attribut). L' .champ attribut est un SortedDict (l'un de Django structures de données internes) qui ne fournit pas de toute façon de réorganiser la clé:des paires de valeurs. Il n'est toutefois fournir un moyen de les insérer à un indice donné, mais qui permettrait de déplacer les éléments de la classe des membres et dans le constructeur. Cette méthode pourrait fonctionner, mais rendre le code moins lisible. La seule autre façon je vois ajustement est de modifier le cadre lui-même qui l'est moins-que-optimale dans la plupart des situations.
En bref, le code pourrait devenir quelque chose comme ceci:
class edit_form(forms.Form):
summary = forms.CharField()
description = forms.CharField(widget=forms.TextArea)
class create_form(edit_form):
def __init__(self,*args,**kwargs):
forms.Form.__init__(self,*args,**kwargs)
self.fields.insert(0,'name',forms.CharField())
Que shut me up 🙂
- Ce cours de nombreuses années plus tard, je suis sûr que vous le savez déjà, mais les noms de classe en python devrait toujours être "Camelcase". Seuls les noms de méthode "named_with_underscore".
- vouliez-vous dire "camelcase"? 🙂
- TitleCase est le terme exact, je crois.
Vous devez vous connecter pour publier un commentaire.
De Django 1.9+
Django 1.9 ajoute une nouvelle
Form
attribut,field_order
, permettant de commander le terrain, quel que soit leur ordre de déclaration dans la classe.Champs manquants dans
field_order
garder leur ordre dans la classe et sont ajoutés après ceux spécifiés dans la liste. L'exemple ci-dessus sera de produire des champs dans cet ordre:['author', 'summary', 'description', 'notes']
Voir la documentation: https://docs.djangoproject.com/en/stable/ref/forms/api/#notes-on-field-ordering
Jusqu'à Django 1.6
J'ai eu ce même problème et j'ai trouvé une autre technique pour la réorganisation des champs de la Django Livre De Recettes:
forms.Form
. En cas deforms.ModelForm
, vous devez définir ce dans le imbriquésclass Meta
, dansfields
attribut. Voir ici: stackoverflow.com/questions/2893471/...collections.OrderedDict
De Django 1.9: https://docs.djangoproject.com/en/1.10/ref/forms/api/#notes-on-field-ordering
Réponse originale à cette question: Django 1.9 soutien à cette par défaut sur le formulaire avec
field_order
:https://github.com/django/django/commit/28986da4ca167ae257abcaf7caea230eca2bcd80
J'ai utilisé la solution posté par Séléné, mais trouve qu'elle a enlevé tous les champs qui n'étaient pas affectés à keyOrder. Le formulaire que je suis sous-classement a beaucoup de champs afin que cela ne fonctionnait pas très bien pour moi. J'ai codé cette fonction pour résoudre le problème à l'aide de akaihola réponse, mais si vous voulez qu'il fonctionne comme Selene est tout ce que vous devez faire est de régler
throw_away
àTrue
.C'est la façon dont je l'utilise dans mon code:
Il semble que, à un certain point, la structure sous-jacente de l'ordre des champs a été modifié à partir d'un django spécifiques
SordedDict
à un standard pythonOrderedDict
Ainsi, dans la 1.7, j'ai eu à faire ce qui suit:
Je suis sûr que quelqu'un pourrait golf que dans deux ou trois lignes, mais pour S. O. fins je pense montrant clairement comment il fonctionne, c'est mieux que cleaver.
Vous pouvez également créer un décorateur à l'ordre des champs (inspiré par Joshua solution):
Cela permettra d'assurer que tous les champs transmis à la décoratrice venir en premier.
Vous pouvez l'utiliser comme ceci:
La accepté de répondre à l'approche fait appel à un interne de Django formes API qui a été changé dans Django 1.7. L'équipe du projet est d'avis qu'il ne devrait jamais avoir été utilisé en premier lieu. Je vais maintenant utiliser cette fonction pour réorganiser mes formes. Ce code permet l'utilisation d'un
OrderedDict
:Que j'utilise dans les classes comme ceci:
Voir les notes en cette SORTE de question sur le chemin de Django reinhardt, les internes de garder une trace de l'ordre des champs, et les réponses comprennent des suggestions sur la façon de "réorganiser" les champs à votre convenance (en fin de compte, ça revient à jouer avec le
.fields
attribut).D'autres méthodes pour changer l'ordre des champs:
Pop et d'insertion:
Pop-et-append:
Pop-et-ajout-tout:
Commandé-copie:
Mais Selene est une approche de l'Django livre de cuisine se sent encore plus claire de tous.
OrderedDict
Basé sur une réponse par @akaihola et mis à jour pour fonctionner avec la dernière version de Django 1.5
self.fields.insert
est amorti.Dans l'au-dessus de nous, l'extension d'un EasyContactUsForm de la classe de base tel qu'il est défini dans django-easycontactus paquet.
J'ai construit un formulaire "ExRegistrationForm' hérité de la "RegistrationForm" de Django-Enregistrement-Redux. J'ai dû faire face à deux questions, l'une était de réordonner les champs sur la sortie html de la page une fois que le nouveau formulaire a été créé.
J'ai résolu comme suit:
1. QUESTION 1: Supprimer le nom d'utilisateur dans le Formulaire d'Inscription: En my_app.forms.py
2. QUESTION 2: FirstName et LastName apparaissent sur le dessus: En templates/registration/registration_form.html
Vous pouvez afficher individuellement les champs dans l'ordre que vous voulez. Ce serait aider dans le cas où le nombre de champs sont moins, mais pas si vous avez un grand nombre de champs, où il devient pratiquement impossible d'écrire dans le formulaire.
Les réponses ci-dessus sont juste, mais incomplète. Elles ne fonctionnent que si tous les champs sont définis comme des variables de classe. Qu'en dynamique des champs de formulaire qui doivent être définis dans le intitialiser (
__init__
)?Le ci-dessus ne fonctionnera jamais pour
val
mais va travailler pourfield1
etfield2
(si nous réorganiser). Vous voudrez peut-être essayer de définirfield_order
dans l'initialiser:mais cela échouera également parce que le domaine de commande est fixé avant l'appel à
super()
.Donc la seule solution est le constructeur (
__new__
) et de définirfield_order
à une variable de classe.