#23130: BooleanField should not override 'blank' if choices are specified
-------------------------------------+-------------------------------------
     Reporter:  jonash               |                    Owner:  tushar
         Type:  Bug                  |                   Status:  assigned
    Component:  Database layer       |                  Version:  master
  (models, ORM)                      |               Resolution:
     Severity:  Normal               |             Triage Stage:  Accepted
     Keywords:                       |      Needs documentation:  0
    Has patch:  0                    |  Patch needs improvement:  0
  Needs tests:  0                    |                    UI/UX:  0
Easy pickings:  0                    |
-------------------------------------+-------------------------------------

Comment (by jonashaag):

 Having given this whole business some hours' thought, I actually believe
 that making a difference between BooleanField and NullBooleanField is
 fundamentally wrong. I know NullBooleanField has been in Django from the
 beginning and removing it/changing BooleanField is a nightmare in terms of
 backwards compatibility.

 Still I'd like to propose a better implementation in form of this patch:
 https://gist.github.com/jonashaag/d8a9f82d88c60c103189 (This passes the
 complete test suite except for a handful of minor now-outdated tests!)

 In this version, BooleanField behaves much more like any other field,
 simplifying both the implementation and the usage. `blank` may be used
 freely as with any other field. The same applies to `null`. By default, it
 renders as a checkbox and does not allow `None` (i.e. `blank=False` like
 with any other field). If `blank` is set to True, it renders as choices
 with an additional blank option. It also renders as choices if `choices`
 is given.

 `NullBooleanField` stays as a mere wrapper for `BooleanField` with
 `blank=null=True`.

 Here is a shortened version of the new implementation:

 {{{
 #!python
 class BooleanField(Field):
     empty_strings_allowed = False
     default_error_messages = {
         'invalid': _("'%(value)s' value must be either True or False."),
     }
     description = _("Boolean (Either True or False)")

     def get_internal_type(self):
         return "BooleanField"

     def to_python(self, value):
         if value is None:
             return value
         if value in (True, False):
             # if value is 1 or 0 than it's equal to True or False, but we
 want
             # to return a true bool for semantic reasons.
             return bool(value)
         if value in ('t', 'True', '1'):
             return True
         if value in ('f', 'False', '0'):
             return False
         raise exceptions.ValidationError(
             self.error_messages['invalid'],
             code='invalid',
             params={'value': value},
         )

     # ...

     def formfield(self, **kwargs):
         if self.blank or self.choices:
             return super(BooleanField, self).formfield(**kwargs)
         else:
             # In the checkbox case, 'required' means "must be checked (=>
 true)",
             # which is different from the choices case ("must select some
 value").
             # Since we want to allow both True and False
 (checked/unchecked) choices,
             # set 'required' to False.
             defaults = {'form_class': forms.BooleanField,
                         'required': False}
             defaults.update(kwargs)
             return super(BooleanField, self).formfield(**defaults)
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/23130#comment:14>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/064.0a52a1a8615dd334b75205784a8f6ff1%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to