django: how to change values for nullbooleanfield in a modelform?
In the docs, the nullbooleanfield
is represented as a <select> box with "Unknown", "Yes" and "No开发者_C百科" choices.
How can I change the values of select
to some other more meaningful texts and map it back to the yes,no and unknown values in my modelform
?
For example I have yes_no_required = models.NullBooleanField()
and I would like to have 'yes I acknowledge this'
, 'no, I do not like this'
and 'I do not know now'
mapping to yes, no and required accordingly.
I spent half an hour putting together a demo just to prove to myself this works:
CHOICES = (
(None, "I do not know now"),
(True, "Yes I acknowledge this"),
(False, "No, I do not like this")
)
class Demo(models.Model):
yes_no_required = models.NullBooleanField(choices = CHOICES)
class DemoForm(forms.ModelForm):
class Meta:
model = Demo
I looked in the Django source code. Everything can accept a choices array. Obviously, for some of those that doesn't make sense, but it's possible.
You can handle this in a form (withouth modifying the models) like this:
forms.NullBooleanField(
widget=forms.RadioSelect(renderer=HorizontalRadioRendererSpace,
choices=CHOICES),
label='...',
required=False)
I think it is a bad idea to use NullBooleanField for data which can be in three states like: yes/no/unset.
Editing the data works. But the big trouble arises if you want to write a search form for this data.
Then the "empty" values can have two meanings:
- Don't care for this attribute. Include all rows
- Include only these rows, where the column is NULL.
The solution is simple: Use a ChoiceField.
More details here: https://github.com/guettli/programming-guidelines/blob/master/README.rst
You can modify your field widget in your ModelForm meta class:
CHOICES = (
(None, "I do not know now"),
(True, "Yes I acknowledge this"),
(False, "No, I do not like this"),
)
class DemoForm(forms.ModelForm):
class Meta:
model = Demo
fields = ("demo_field",)
widgets = {
'demo_field': forms.RadioSelect(choices = CHOICES),
}
Simple approach would be to change widget choices in your form:
class YourForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(YourForm, self).__init__(*args, **kwargs)
new_choices = ((1, 'I do not know now'),
(2, 'Yes I acknowledge this'),
(3, 'No, I do not like this'))
self.fields['your_field'].widget.choices = new_choices
精彩评论