#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 django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
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