authentic/src/authentic2/a2_rbac/fields.py

63 lines
2.3 KiB
Python

# authentic2 - versatile identity manager
# Copyright (C) 2010-2019 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django import forms
from django.db.models import NullBooleanField
class UniqueBooleanField(NullBooleanField):
"""BooleanField allowing only one True value in the table, and preventing
problems with multiple False values by implicitely converting them to
None."""
def __init__(self, *args, **kwargs):
kwargs['unique'] = True
kwargs['blank'] = True
kwargs['null'] = True
kwargs['default'] = False
super(NullBooleanField, self).__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(NullBooleanField, self).deconstruct()
del kwargs['null']
del kwargs['blank']
del kwargs['unique']
del kwargs['default']
return name, path, args, kwargs
def to_python(self, value):
value = super(UniqueBooleanField, self).to_python(value)
if value is None:
return False
return value
def get_db_prep_value(self, value, connection, prepared=False):
value = super(UniqueBooleanField, self).get_db_prep_value(value, connection, prepared=prepared)
if value is False:
return None
return value
def formfield(self, **kwargs):
# Unlike most fields, BooleanField figures out include_blank from
# self.null instead of self.blank.
if self.choices:
include_blank = False
defaults = {'choices': self.get_choices(include_blank=include_blank)}
else:
defaults = {'form_class': forms.BooleanField}
defaults.update(kwargs)
return super(NullBooleanField, self).formfield(**defaults)