C'è un widget in Django 1.0.2 per il rendering di un models.BooleanField
come due pulsanti di opzione anziché una casella di controllo?Django BooleanField come pulsanti radio?
risposta
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
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
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
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
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'),
...
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.
La soluzione più pulita e più "Django" di gran lunga. Grazie! –
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
Penso che il codice aggiuntivo per localizzarlo possa distrarre dal punto. Un esercizio per il lettore;) – eternicode
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à :)
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+
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)
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')]))
Questa dovrebbe essere la risposta corretta. –
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
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.')
])}
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
Dovrebbe essere davvero aggiornato poiché, come nota @dar, questo in realtà non funzionerà poiché 'bool ('False')' => 'True'. –
@Daniel, non funziona, bool ('False') restituisce True –