guettli
guettli

Reputation: 27997

Search Form for NullBooleanField

I write a search form for a django model which contains column is_ok as a NullBooleanField.

I want to have 4 choices:

Up to now I use this:

is_ok = forms.NullBooleanField(required=False)

But this renders only three options (as drop-down list).

How to distinguish between "is NULL" and "not set" here?

Upvotes: 1

Views: 234

Answers (1)

Antoine Pinsard
Antoine Pinsard

Reputation: 35002

As @Alasdair said, you'll have to create a custom field:

class UnsetType:
    def __str__(self):
        return '__unset__'

Unset = UnsetType()

class UnsetOrNullBooleanSelect(NullBooleanSelect):
    def __init__(self, attrs=None):
        choices = (
            ('__unset__', ugettext_lazy('Unset')),
            ('1', ugettext_lazy('Unknown')),
            ('2', ugettext_lazy('Yes')),
            ('3', ugettext_lazy('No')),
        )
        super().__init__(attrs, choices)

    def render(self, name, value, attrs=None):
        try:
            value = {
                True: '2', False: '3', None: '1',
                '2': '2', '3': '3', '1': '1',
            }[value]
        except KeyError:
            value = '__unset__'
        return super().render(name, value, attrs)

    def value_from_datadict(self, data, files, name):
        value = data.get(name)
        return {
            '1': None, None: None, 'None': None, 'none': None, 'null': None,
            '2': True, True: True, 'True': True,
            '3': False, 'False': False, False: False,
        }.get(value, Unset)

class UnsetOrNullBooleanField(NullBooleanField):

    widget = UnsetOrNullBooleanSelect

    def to_python(self, value):
        if value in (True, 'True', 'true', '1'):
            return True
        elif value in (False, 'False', 'false', '0'):
            return False
        elif value in (None, 'None', 'none', 'null'):
            return None
        else:
            return Unset

Upvotes: 1

Related Questions