django-models modelform - Django BooleanField als Optionsfelder?




forms fields (9)

Gibt es ein Widget in Django 1.0.2, um ein models.BooleanField als zwei Optionsfelder anstelle einer Checkbox zu rendern?


Answers

Django 1.2 hat die Meta-Option "Widgets" für Modellformen hinzugefügt:

Geben Sie in Ihrem models.py die "Auswahlmöglichkeiten" für Ihr boolesches Feld an:

BOOL_CHOICES = ((True, 'Yes'), (False, 'No'))

class MyModel(models.Model):
    yes_or_no = models.BooleanField(choices=BOOL_CHOICES)

Geben Sie dann in Ihrer forms.py das RadioSelect-Widget für dieses Feld an:

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        widgets = {
            'yes_or_no': forms.RadioSelect
        }

Ich habe dies mit einer SQLite-Datenbank getestet, die auch boolesche Werte als 1/0-Werte speichert, und es scheint ohne eine benutzerdefinierte Zwangsfunktion zu funktionieren.


Hier ist eine schnelle & schmutzige Zwangsfunktion mit Lambda, die das "False" -> True-Problem umgeht:

...
boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'),
...

Wenn Sie die Antwort von Daniel Roseman etwas ändern, können Sie das Problem bool ("False") = True kurz und bündig beheben, indem Sie stattdessen nur ints verwenden:

class MyModelForm(forms.ModelForm):
    boolfield = forms.TypedChoiceField(coerce=lambda x: bool(int(x)),
                   choices=((0, 'False'), (1, 'True')),
                   widget=forms.RadioSelect
                )

class Meta:
     model = MyModel

Sie können dies tun, indem Sie die Felddefinition in ModelForm überschreiben:

class MyModelForm(forms.ModelForm):
    boolfield = forms.TypedChoiceField(
                   coerce=lambda x: x == 'True',
                   choices=((False, 'False'), (True, 'True')),
                   widget=forms.RadioSelect
                )

    class Meta:
         model = MyModel

Eine andere Lösung:

from django import forms
from django.utils.translation import ugettext_lazy as _

def RadioBoolean(*args, **kwargs):
    kwargs.update({
        'widget': forms.RadioSelect,
        'choices': [
            ('1', _('yes')),
            ('0', _('no')),
        ],
        'coerce': lambda x: bool(int(x)) if x.isdigit() else False,
    })
    return forms.TypedChoiceField(*args, **kwargs)

Bedenken Sie auch, dass MySQL Tinyint für Boolean verwendet, also ist True / False tatsächlich 1/0. Ich habe diese Zwangsfunktion benutzt:

def boolean_coerce(value):
    # value is received as a unicode string
    if str(value).lower() in ( '1', 'true' ):
        return True
    elif str(value).lower() in ( '0', 'false' ):
        return False
    return None

Wie @ternicodes Antwort, aber ohne das Modell zu ändern:

class MyModelForm(forms.ModelForm):
    yes_no = forms.RadioSelect(choices=[(True, 'Yes'), (False, 'No')])

    class Meta:
        model = MyModel
        widgets = {'boolfield': yes_no}

Ich denke, das funktioniert nur in Django 1.2+


Hier ist der einfachste Ansatz, den ich finden könnte (ich benutze Django 1.5):

class MyModelForm(forms.ModelForm):
    yes_no = forms.BooleanField(widget=RadioSelect(choices=[(True, 'Yes'), 
                                                            (False, 'No')]))

@staff_member_required Mitarbeitermitgliedschaft ausreichend ist, können Sie den Dekorateur @staff_member_required :

from django.contrib.admin.views.decorators import staff_member_required

@staff_member_required
def my_view(request):
    ...




django django-models django-forms