2009-05-12 8 views

risposta

58

si potrebbe fare questo sovrascrivendo la definizione del campo nella 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

Purtroppo questo non ha funzionato, perché il coerce = bool viene passato un valore stringa, e non il valore booleano e bool ("False") => True. Quindi ho dovuto scrivere una funzione coercitiva personalizzata per prendere il valore stringa e convertirlo in bool, quindi ha funzionato. Grazie per il puntatore. – dar

+1

Dovrebbe essere davvero aggiornato poiché, come nota @dar, questo in realtà non funzionerà poiché 'bool ('False')' => 'True'. –

+0

@Daniel, non funziona, bool ('False') restituisce True –

3

anche ricordare che MySQL utilizza tinyint per booleana, così vero/falso sono in realtà 1/0. Ho usato questa funzione coerce:

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

Modifica risposta di Daniel Roseman un po ', si potrebbe risolvere il bool ("False") = True problema succintamente da solo utilizzando int invece:

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

Questo non funziona sul mio modulo di modifica. Il valore corrente del campo non viene estratto dal modello. Ho usato invece la risposta di eternicode. – Dave

5

Ecco un rapido & sporco funzione di costringere utilizzando lambda, che aggira il "false" -> true problema:

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

Django 1.2 ha aggiunto l'opzione di Meta per modelforms "widget":

Nella tua models.py, specificare le "scelte" per il campo booleano:

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

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

Poi, nel vostro forms.py, specificare il widget di RadioSelect per quel campo:

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

Ho provato questo con un db SQLite, che memorizza anche i booleani come valori 1/0, e sembra funzionare bene senza una funzione coercitiva personalizzata.

+4

La soluzione più pulita e più "Django" di gran lunga. Grazie! –

+0

Questo è fantastico. Lo modifico leggermente per consentire versioni localizzate di "Sì" e "No" usando "da django.utils.translation import ugettext_lazy as _" e aggiornando "BOOL_CHOICES" come: 'BOOL_CHOICES = ((Vero, _ ('Sì')), (False, _ ('No'))) ' – tatlar

+5

Penso che il codice aggiuntivo per localizzarlo possa distrarre dal punto. Un esercizio per il lettore;) – eternicode

3

Come c'è un problema nella risposta di @Daniel Roseman, bool ('False') -> Vero, quindi ora ho combinato due risposte qui per fare una soluzione.

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 

Ora, questo funzionerà :)

3

Uguale @ di eternicode risposta, ma senza modificare il modello:

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

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

penso che questo funziona solo in Django 1.2+

3

An altra soluzione:

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

Ecco l'approccio più semplice che ho trovato (sto usando Django 1.5):

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

Questa dovrebbe essere la risposta corretta. –

+0

Verificare che questa soluzione funzioni, ma consultare la [nota nei documenti] (https://docs.djangoproject.com/en/1.10/ref/forms/fields/#booleanfield). È necessario impostare required = False sul campo. – grokpot

9

In Django 1.6, i seguenti ha lavorato per me:

class EmailSettingsForm(ModelForm): 

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