96 votes

Comment Django connaît-il l'ordre de restitution des champs de formulaire?

Si j'ai un formulaire Django tel que:

 class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField()
    sender = forms.EmailField()
 

Et j'appelle la méthode as_table () d'une instance de ce formulaire, Django rendra les champs dans le même ordre que celui spécifié ci-dessus.

Ma question est la suivante: comment Django connaît-il l'ordre dans lequel les variables de classe ont été définies?

(De plus, comment puis-je remplacer cet ordre, par exemple lorsque je veux ajouter un champ à partir de la méthode init de la classe?)

90voto

holdenweb Points 3632

[NOTE: cette réponse est aujourd'hui quelque peu désuet - veuillez voir la discussion ci-dessous].

Si f est une forme, ses champs sont f.les champs, qui est un django.utils.datastructures.SortedDict (il présente les éléments dans l'ordre où ils sont ajoutés). Après la construction de f.champs a un keyOrder attribut, qui est une liste contenant les noms de champ dans l'ordre où ils doivent être présentés. Vous pouvez le régler sur le bon de commande (si vous avez besoin de soins de l'exercice pour vous assurer de ne pas omettre des éléments ou ajouter des extras).

Voici un exemple que j'ai créé dans mon projet actuel:

class PrivEdit(ModelForm):
    def __init__(self, *args, **kw):
        super(ModelForm, self).__init__(*args, **kw)
        self.fields.keyOrder = [
            'super_user',
            'all_districts',
            'multi_district',
            'all_schools',
            'manage_users',
            'direct_login',
            'student_detail',
            'license']
    class Meta:
        model = Privilege

40voto

Greg Points 7098

Je suis allé de l'avant et d'avoir répondu à ma propre question. Voici la réponse de référence pour l'avenir:

Dans Django form.py fait un peu de la magie noire à l'aide de l' __new__ méthode pour charger vos variables de classe en fin de compte en self.fields dans l'ordre défini dans la classe. self.fields est un Django SortedDict instance (définie en datastructures.py).

Donc, pour remplacer ce, dire dans mon exemple, tu voulais de l'expéditeur venir en premier, mais nécessaire de l'ajouter dans un init méthode, vous devez faire:

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField()
    def __init__(self,*args,**kwargs):
        forms.Form.__init__(self,*args,**kwargs)
        #first argument, index is the position of the field you want it to come before
        self.fields.insert(0,'sender',forms.EmailField(initial=str(time.time())))

11voto

Hugh Saunders Points 71

Les champs sont répertoriés dans l'ordre dans lequel ils ont été définis dans ModelClass._meta.fields. Mais si vous voulez modifier l'ordre dans Form, vous pouvez le faire en utilisant la fonction keyOrder. Par exemple :

 class ContestForm(ModelForm):
  class Meta:
    model = Contest
    exclude=('create_date', 'company')

  def __init__(self, *args, **kwargs):
    super(ContestForm, self).__init__(*args, **kwargs)
    self.fields.keyOrder = [
        'name',
        'description',
        'image',
        'video_link',
        'category']
 

5voto

zgoda Points 8549

Les champs de formulaire ont un attribut pour l'ordre de création, appelé creation_counter . .fields attribut est un dictionnaire, il est donc simple de l'ajouter au dictionnaire et de modifier les attributs creation_counter dans tous les champs afin de refléter le nouvel ordre - (jamais essayé, cependant).

5voto

nosklo Points 75862

Utilisez un compteur dans la classe Field. Trier par ce compteur:

 import operator
import itertools

class Field(object):
    _counter = itertools.count()
    def __init__(self):
        self.count = Field._counter.next()
        self.name = ''
    def __repr__(self):
        return "Field(%r)" % self.name

class MyForm(object):
    b = Field()
    a = Field()
    c = Field()

    def __init__(self):
        self.fields = []
        for field_name in dir(self):
            field = getattr(self, field_name)
            if isinstance(field, Field):
                field.name = field_name
                self.fields.append(field)
        self.fields.sort(key=operator.attrgetter('count'))

m = MyForm()
print m.fields # in defined order
 

Sortie:

 [Field('b'), Field('a'), Field('c')]
 


Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X