2009-05-12 7 views

Antwort

58

Sie können dies tun, indem Sie die Felddefinition in der 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 
+7

Leider hat dies nicht funktioniert, weil die coerce = bool wird ein Zeichenfolgenwert und nicht der boolesche Wert und bool ("False") => True übergeben. Also musste ich eine benutzerdefinierte Coerce-Funktion schreiben, um den String-Wert zu übernehmen und nach bool zu konvertieren, dann funktionierte es. Danke für den Zeiger. – dar

+1

Sollte wirklich aktualisiert werden, da @dar feststellt, dass dies eigentlich NICHT funktioniert seit 'bool ('False')' => 'True'. –

+0

@Daniel, es funktioniert nicht, bool ('False') gibt True zurück –

3

Denken Sie auch daran, dass MySQL Tinyint für Boolean, so Wahr/Falsch sind eigentlich 1/0 verwendet. Ich habe diese coerce Funktion:

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 
30

Ändern Daniel Roseman Antwort ein wenig, man konnte die Bool beheben ("False") kurz und bündig wahre Problem = von nur statt Ints mit:

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 
+2

Dies funktioniert nicht auf meinem Bearbeitungsformular. Der aktuelle Wert des Felds wird nicht aus dem Modell abgerufen. Ich habe stattdessen eternicodes Antwort verwendet. – Dave

5

Hier ist eine schnelle & schmutzig coerce Funktion Lambda verwenden, die um den "false" wird -> True Problem:

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

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

In Ihrem models.py, die "Auswahl" für Ihre boolean Feld angeben:

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

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

in Ihrem forms.py Dann, für das Feld der RadioSelect Widget angeben:

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.

+4

Die sauberste und "Django" Lösung mit Abstand. Vielen Dank! –

+0

Das ist großartig. Ich würde es leicht modifizieren, um lokalisierte Versionen von 'Ja' und 'Nein' zu erlauben, indem 'von django.utils.translation import ugettext_lazy als _' verwendet und 'BOOL_CHOICES' aktualisiert wird: ' BOOL_CHOICES = ((True, _ ("Ja")), (Falsch, _ ('Nein'))) ' – tatlar

+5

Ich denke, der zusätzliche Code zur Lokalisierung würde von dem Punkt ablenken. Eine Übung für den Leser;) – eternicode

3

Da gibt es ein Problem in @Daniel Roseman Antwort, Bool ('False') -> True, so jetzt habe ich zwei Antworten hier kombiniert, um eine Lösung zu machen.

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 

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

class Meta: 
    model = MyModel 

Jetzt wird diese Arbeit :)

3

Gleiche wie @ eternicode 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+

3

Ein 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) 
6

Hier ist der einfachste Ansatz, den ich finden konnte (Ich verwende Django 1.5):

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

Dies sollte die richtige Antwort sein. –

+0

Die Überprüfung dieser Lösung funktioniert, aber siehe [Hinweis in den Dokumenten] (https://docs.djangoproject.com/en/1.10/ref/forms/fields/#booleanfield). Sie müssen erforderlich = False für das Feld festlegen. – grokpot

9

In Django 1.6, die für mich gearbeitet folgende:

class EmailSettingsForm(ModelForm): 

    class Meta: 
     model = EmailSetting 
     fields = ['setting'] 
     widgets = {'setting': RadioSelect(choices=[ 
      (True, 'Keep updated with emails.'), 
      (False, 'No, don\'t email me.')    
     ])} 
Verwandte Themen