2 votes

Comment créer manuellement un champ de sélection à partir d'un ModelForm dans Django ?

J'ai un ModelForm où l'un des champs (nommé creator ) est un ForeignKey Ainsi, pour {{ form.creator }} Django rend l'élément <select> comme ceci :

<select id="id_approver" name="approver">
    <option selected="selected" value="">---------</option>
    <option value="1">hobbes3</option>
    <option value="2">tareqmd</option>
    <option value="3">bob</option>
    <option value="4">sam</option>
    <option value="5">jane</option>
</select>

Mais je souhaite ajouter un onchange afin de pouvoir utiliser AJAX ultérieurement pour faire autre chose. Je souhaite également modifier l'attribut --------- pour dire autre chose et afficher le nom complet des approbateurs, et non leur nom d'utilisateur.

Est-il possible d'obtenir une liste d'approbateurs possibles et de générer mes propres options de sélection ? Un peu comme

<select id="id_approver" name="approver" onchange="some_ajax_function()">
    <option select="selected" value="0">Choose a user</option>
{% for approver in form.approver.all %} <!-- This won't work -->
    <option value="{{ approver.pk }}">{{ approver.get_full_name }}</option>
{% endfor %}
</select>

Je pense aussi que si la liste des approbateurs devient trop importante (plus de 50 par exemple), j'aurai besoin d'une sorte de champ auto-complet consultable pour l'approbateur. Dans ce cas, je devrai certainement écrire mon propre code HTML.

Au cas où quelqu'un en aurait besoin, mon ModelForm ressemble à ceci :

class OrderCreateForm( ModelForm ) :
    class Meta :
        model = Order
        fields = (
            'creator',
            'approver',
            'work_type',
            'comment',
        )

1voto

Burhan Khalid Points 50578

Les Documentation de ModelChoiceField explique comment procéder.

Pour modifier l'étiquette vide :

empty_label

    By default the <select> widget used by ModelChoiceField
    will have an empty choice at the top of the list. You can change the text
    of this label (which is "---------" by default) with the empty_label
    attribute, or you can disable the empty label entirely by setting
    empty_label to None:

    # A custom empty label
    field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)")

    # No empty label
    field2 = forms.ModelChoiceField(queryset=..., empty_label=None)

Quant à votre deuxième question, elle est également expliquée dans la documentation :

The __unicode__ method of the model will be called to generate string
representations of the objects for use in the field's choices;
to provide customized representations, subclass ModelChoiceField and override
label_from_instance. This method will receive a model object, and should return
a string suitable for representing it. For example:

class MyModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return "My Object #%i" % obj.id

Enfin, pour passer des commandes ajax personnalisées, utilisez l'option attrs pour le widget de sélection (qui est utilisé dans le champ ModelForm).

Au final, vous devriez obtenir quelque chose comme ceci :

creator = MyCustomField(queryset=...,
                        empty_label="Please select",
                        widget=forms.Select(attrs={'onchange':'some_ajax_function()'})

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