2009-05-12 17 views

Odpowiedz

58

Można to zrobić poprzez nadpisanie definicji pola w ModelForm:

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

Niestety to nie działa, ponieważ przymusić = bool jest przekazywany wartość łańcucha, a nie wartość boolean i bool ("False") => True. Musiałem więc napisać niestandardową funkcję coerce, aby pobrać wartość ciągu i przekonwertować na wartość bool, a następnie zadziałało. Dzięki za wskaźnik. – dar

+1

Naprawdę powinien zostać zaktualizowany, ponieważ, jak zauważa @dar, to faktycznie NIE będzie działało od 'bool ('False')' => 'True'. –

+0

@Daniel, to nie działa, bool ('False') zwraca True –

3

Należy również pamiętać, że MySQL używa tinyint dla Boolean, więc Prawda/Fałsz są rzeczywiście 1/0. Użyłem tej funkcji przymusić:

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

Modyfikowanie odpowiedź Daniela Roseman trochę, można naprawić bool („false”) = True problemu zwięźle używając tylko ints zamiast:

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

To nie działa w moim formularzu edycji. Bieżąca wartość pola nie jest pobierana z modelu. Zamiast tego użyłem odpowiedzi eternicode. – Dave

5

Oto krótki & brudny funkcja wymusić za pomocą lambda, który dostaje się wokół "false" -> true problemu:

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

Django 1.2 dodała "widgety" Meta opcję modelforms:

W swojej models.py, określenie "wybory" do logicznej polu:

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

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

Następnie w forms.py określ widget RadioSelect na tym polu:

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

Przetestowałem to z db SQLite, który również przechowuje wartości logiczne jako wartości 1/0, i wydaje się, że działa dobrze bez niestandardowej funkcji Coerce.

+4

Zdecydowanie najczystszym i najbardziej "django" rozwiązaniem. Dzięki! –

+0

To jest świetne. Zmodyfikuję go nieznacznie, aby umożliwić zlokalizowane wersje "Tak" i "Nie", używając 'from django.utils.translation importuj ugettext_lazy jako _' i aktualizując' BOOL_CHOICES' na: 'BOOL_CHOICES = ((True, _ ("Tak")), (Fałsz, _ ("Nie"))) ' – tatlar

+5

Myślę, że dodatkowy kod do zlokalizowania go odciągnie od punktu. Ćwiczenie dla czytelnika;) – eternicode

3

Jak jest problem z odpowiedzią @Daniel Roseman, bool ("Fałsz") -> Prawda, więc teraz połączyłem dwie odpowiedzi tutaj, by zrobić jedno rozwiązanie.

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 

Teraz to będzie działać :)

3

samo jak na @ eternicode odpowiedź, ale bez modyfikacji modelu:

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

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

myślę, że to działa tylko w Django 1.2+

3

An inne rozwiązanie:

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

Oto najprostsze podejście udało mi się znaleźć (używam Django 1.5):

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

To powinno być właściwą odpowiedzią. –

+0

Sprawdzanie tego rozwiązania działa, ale zobacz [uwaga w dokumentach] (https://docs.djangoproject.com/en/1.10/ref/forms/fields/#booleanfield). Musisz ustawić required = False na polu. – grokpot

9

W Django 1.6, następujące pracował dla mnie:

class EmailSettingsForm(ModelForm): 

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