it-swarm.com.de

Leeres Label ChoiceField Django

Wie lässt sich das Label von ChoiceField wie ModelChoiceField verhalten? Gibt es eine Möglichkeit, einen empty_label festzulegen oder zumindest ein leeres Feld anzuzeigen?

Forms.py:

    thing = forms.ModelChoiceField(queryset=Thing.objects.all(), empty_label='Label')
    color = forms.ChoiceField(choices=COLORS)
    year = forms.ChoiceField(choices=YEAR_CHOICES)

Ich habe die hier vorgeschlagenen Lösungen ausprobiert:

Stack Overflow Q - Die Einstellung CHOICES = [('','All')] + CHOICES führte zu einem internen Serverfehler.

Stack Overflow Q2 - Nachdem Sie ('', '---------'), in meinen Auswahlmöglichkeiten definiert haben, wird standardmäßig der erste Eintrag in der Liste verwendet, nicht die Auswahl ('', '---------'),

Gist - Versuchte mit EmptyChoiceField, das hier definiert wurde, funktionierte jedoch nicht mit Django 1.4.

Aber keiner davon hat für mich funktioniert. Wie würden Sie dieses Problem lösen? Danke für deine Ideen!

32
Nick B

Hier ist die Lösung, die ich verwendet habe:

from myapp.models import COLORS

COLORS_EMPTY = [('','---------')] + COLORS

class ColorBrowseForm(forms.Form):
    color = forms.ChoiceField(choices=COLORS_EMPTY, required=False, widget=forms.Select(attrs={'onchange': 'this.form.submit();'}))
12
Nick B

Siehe die Dokumentation zu Django 1.11 auf ChoiceField . Der 'empty_value' für das ChoiceField wird als leere Zeichenfolge '' definiert, daher sollte Ihre Liste von Tupeln einen Schlüssel von '' enthalten, der dem Wert zugeordnet ist, den Sie für den leeren Wert anzeigen möchten. 

### forms.py
from Django.forms import Form, ChoiceField

CHOICE_LIST = [
    ('', '----'), # replace the value '----' with whatever you want, it won't matter
    (1, 'Rock'),
    (2, 'Hard Place')
]

class SomeForm (Form):

    some_choice = ChoiceField(choices=CHOICE_LIST, required=False)

Hinweis: Sie können einen Formularfehler vermeiden, wenn Sie möchten, dass das Formularfeld optional ist, indem Sie 'required = False' verwenden.

Wenn Sie bereits eine CHOICE_LIST ohne einen leeren_Wert haben, können Sie einen einfügen, so dass er zuerst im Dropdown-Menü des Formulars angezeigt wird:

CHOICE_LIST.insert(0, ('', '----'))
33
Fiver

Sie können dies versuchen (vorausgesetzt, Ihre Auswahl sind Tupel):

blank_choice = (('', '---------'),)
...
color = forms.ChoiceField(choices=blank_choice + COLORS)
year = forms.ChoiceField(choices=blank_choice + YEAR_CHOICES)

Ich kann auch nicht aus Ihrem Code erkennen, ob es sich hierbei um ein Formular oder eine ModelForm handelt, aber es ist das letzte, das Formularfeld muss hier nicht neu definiert werden (Sie können die Auswahlmöglichkeiten = FARBEN und Auswahlmöglichkeiten = YEAR_CHOICES direkt in das Modellfeld aufnehmen .

Hoffe das hilft. 

3
reczy

Ich weiß, dass Sie bereits eine Antwort akzeptiert haben, aber ich möchte diese nur posten, falls jemand da draußen auf das Problem stößt, das ich hatte, dh die akzeptierte Lösung funktioniert nicht mit einem ValueListQuerySet. Das EmptyChoiceField , mit dem Sie verlinkt haben, funktioniert perfekt für mich (obwohl ich Django 1.7 verwende).

class EmptyChoiceField(forms.ChoiceField):
    def __init__(self, choices=(), empty_label=None, required=True, widget=None, label=None, initial=None, help_text=None, *args, **kwargs):

        # prepend an empty label if it exists (and field is not required!)
        if not required and empty_label is not None:
            choices = Tuple([(u'', empty_label)] + list(choices))

        super(EmptyChoiceField, self).__init__(choices=choices, required=required, widget=widget, label=label, initial=initial, help_text=help_text, *args, **kwargs) 

class FilterForm(forms.ModelForm):
    #place your other fields here 
    state = EmptyChoiceField(choices=People.objects.all().values_list("state", "state").distinct(), required=False, empty_label="Show All")
2
VT_Drew

Musste 0 anstelle von u '' wegen eines ganzzahligen Feldes im Modell verwenden. (Fehler war ungültiges Literal für int () mit Basis 10: ')

ein leeres Etikett voranstellen, falls vorhanden (und kein Feld erforderlich!)

    if not required and empty_label is not None:
        choices = Tuple([(0, empty_label)] + list(choices))
1
Pat

Ein bisschen zu spät zur Party ..

Wie wäre es, wenn Sie die Auswahl nicht ändern und nur mit einem Widget umgehen?

from Django.db.models import BLANK_CHOICE_DASH

class EmptySelect(Select):
    empty_value = BLANK_CHOICE_DASH[0]
    empty_label = BLANK_CHOICE_DASH[1]

    @property
    def choices(self):
        yield (self.empty_value, self.empty_label,)
        for choice in self._choices:
            yield choice

    @choices.setter
    def choices(self, val):
        self._choices = val

Dann nennen Sie es einfach:

class SomeForm(forms.Form):
    # thing = forms.ModelChoiceField(queryset=Thing.objects.all(), empty_label='Label')
    color = forms.ChoiceField(choices=COLORS, widget=EmptySelect)
    year = forms.ChoiceField(choices=YEAR_CHOICES, widget=EmptySelect)

Natürlich würde die EmptySelect in eine Art common/widgets.py-Code eingefügt werden, und wenn Sie es brauchen, dann verweisen Sie einfach darauf.

0
Javier Buzzi

Es ist nicht dasselbe Formular, aber ich habe es auf folgende Weise gemacht, die von der EmptyChoiceField-Methode inspiriert wurde:

from Django import forms
from ..models import Operator


def parent_operators():
    choices = Operator.objects.get_parent_operators().values_list('pk', 'name')
    choices = Tuple([(u'', 'Is main Operator')] + list(choices))
    return choices


class OperatorForm(forms.ModelForm):
    class Meta:
        model = Operator
        # fields = '__all__'
        fields = ('name', 'abbr', 'parent', 'om_customer_id', 'om_customer_name', 'email', 'status')

    def __init__(self, *args, **kwargs):
        super(OperatorForm, self).__init__(*args, **kwargs)
        self.fields['name'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['abbr'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['parent'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['parent'].choices = parent_operators()
        self.fields['parent'].required = False
        self.fields['om_customer_id'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['om_customer_name'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['email'].widget.attrs.update({'class': 'form-control m-input form-control-sm', 'type': 'email'})enter code here
0
cwhisperer