web-dev-qa-db-fra.com

Comment puis-je répéter les options d'un SelectField dans un modèle?

J'ai un champ de sélection dans le formulaire et je dois maintenant parcourir les options de ce champ.

{{ form.myselect }} me donne ceci:

<select name="myselect" id="id_myselect">
    <option value="" selected="selected">---------</option>
    <option value="2">Item 1</option>
    <option value="3">Item 2</option>
    ...
</select>

Maintenant, je dois ajouter des attributs aux options et à cause de cela, j'ai besoin de:

<select name="myselect" id="id_myselect">
{% for x in form.myselect %}
    <option value="{{ x.id }}">{{ x.name }}</option>
{% endfor %}
</select>

mais il y a une erreur:

Caught TypeError while rendering: 'BoundField' object is not iterable

J'essayais form.myselect.all, form.myselect.option_set mais ça ne donne rien

27
Goran

J'ai eu du mal avec ce problème aujourd'hui et j'ai trouvé la solution. Oui, vous pouvez parcourir les options de la balise select directement dans le modèle. Voici comment le faire dans le modèle:

<select id="id_Customer" name="Customer">
{% for x,y in form.fields.Customer.choices %}
    <option value="{{ x }}"{% if form.fields.Customer.value == x %} selected{% endif %}>{{ y }}</option>
{% endfor %}
</select>

Dans ce cas, j'ai un champ Client dans le formulaire qui a des choix configurés comme suit:

class Some_Form(forms.Form):
    Customer = forms.ChoiceField(label=u'Customer')

    def __init__(self, *args, **kwargs):
        super(Some_Form, self).__init__(*args, **kwargs)
        self.fields['Customer'].choices = [(e.id, e.Customer) for e in Customers.objects.all()]

J'espère que cela t'aides

71
Jaro

Je l'ai fait fonctionner avec:

    <select name="myselect" class="i-can-add-my-own-attrs-now" id="id_myselect">
        {% for id, name in form.myselect.field.choices %}
        <option value="{{ id }}">{{ name }}</option>
        {% endfor %}
    </select>

MAIS VRAIMENT, une meilleure façon de le faire est avec Django-widget-tweaks :

    {% load widget_tweaks %}
    {{ form.myselect|add_class:"i-can-haz-custom-classes-easily" }}

Le faire avec Django-widget-tweaks définira également la valeur par défaut 'selected = "selected"' pour vous, ce qui est super sympa!

23
epylinkn

Je fais de cette façon:

<select id="id_construction_type" name="construction_type" class="form-control input-md">
{% for value, key in form_urban.fields.construction_type.choices %}
    <option value="{{ value }}"{% if form_urban.initial.construction_type == value %} selected {% endif %}>
        {{ key }}
    </option>
{% endfor %}
</select>
7
Cícero Alves

Il s'agit d'une solution plus propre, vous pouvez définir les attributs à l'aide d'un widget personnalisé. De cette façon, vous n'avez pas à rendre le champ manuellement:

class CustomSelectWidget(forms.Select):
    def create_option(self, name, value, *args, **kwargs):
        option = super().create_option(name, value, *args, **kwargs)
        if value:
            instance = self.choices.queryset.get(pk=value)  # get instance
            option['attrs']['custom_attr'] = instance.field_name  # set option attribute
        return option

class SomeForm(forms.ModelForm):
    some_field = forms.ModelChoiceField(
        queryset=SomeModel.objects.all(),
        widget=CustomSelectWidget
    )
2
Pedro

Avec des boutons radio dans votre modèle, utilisez.

    <table>
        {% for x,y in form.fields.Customer.choices %}
        <tr>
            <td><input id="id_Customer_{{x}}" {% if form.fields.Customer.value == x %}checked="checked"{% endif %} name="Customer" type="radio" value="{{x}}" /></td>
            <td>{{ y }}</td>
        </tr>
        {% endfor %}
    </table>
0
user1491229