#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.