Opened 12 years ago
Closed 12 years ago
#22282 closed Uncategorized (needsinfo)
models.BooleanField.blank should be 'False' if BooleanField has choices
| Reported by: | Owned by: | nobody | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.6 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | yes | UI/UX: | no |
Description
There's no way to override the 'blank' property on a boolean field.
If you look at db/models/fields/init.py under BooleanField.__init__() you'll see that blank = True is hard coded.
This gets messy for a couple of reasons:
- It means that doing something like this silently fails. Either it should raise an error (e.g. "blank cannot be set for BooleanField") or in
__init__do a check to only setblank=Trueifkwargs.get('blank')isNone
class MyObj(models.Model):
is_good = models.BooleanField(blank=False) # fails silently since blank = True is hard coded
- It makes me question the strictness of the
blankproperty, if a boolean field in a form can validate when in fact it isFalseand notNone(OK, I'm assuming somewhere that BooleanField converts aNonevalue toFalse?
- Most importantly (and the case where this broke for me) is when I wanted to do something like:
class MyObj(models.Model):
is_good = models.BooleanField(choices=(
(False, "Object is Bad"),
(True, "Object is Good")
)
There's no way to make sure the value is not blank.
My simple fix was to edit BooleanField's __init__ method to do:
def __init__(self, *args, **kwargs):
if not kwargs.get('choices'):
kwargs['blank'] = True
Field.__init__(self, *args, **kwargs)
But now I think about it maybe the fact that BooleanField assumes a None value to be False is another problem as well. I know why - because the default widget is a tickbox, which have the same state for None and False - but maybe the converting of None to False should consider the widget type?
Let's start with form fields. A
BooleanFieldis rendered by default as a checkbox. If it's mandatory (e.g. accept terms & conditions), you setblank = False. If it's optional, you setblank = True.Let's now look at model fields. Only the second case makes sense. That's why Django forces
blank = True. You're right, Django could warn thatblank = Falseis a misconfiguration that probably doesn't do what you expect.If I understand correctly, you'd like to use a different widget, maybe a radio list with two choices. If a value that doesn't match either of your choices is returned, as far as I can tell,
BooleanField.to_pythonis going to raise aValidationError.I don't understand why you're saying that "There's no way to make sure the value is not blank." On the contrary, Django enforces that you always get
True,Falseor an exception at the model layer. As explained above, always gettingTrueor an execption isn't interesting at the model layer.I'm not sure where "
BooleanFieldassumes aNonevalue to beFalse" comes from either.Could you show why your example doesn't work? Either an exception traceback or a failing test case will do. Thank you!