Source code for django_prbac.fields
from django.db import models
import django_prbac.csv
from django_prbac.forms import StringListFormField
[docs]class StringListField(models.TextField):
"""
A Django field for lists of strings
"""
[docs] def is_string_list(self, value):
return isinstance(value, list) and all([isinstance(v, str) for v in value])
[docs] def to_python(self, value):
"""
Best-effort conversion of "any value" to a string list.
It does not try that hard, because curious values probably indicate
a mistake and we should fail early.
"""
# Already the appropriate python type
if self.is_string_list(value):
return value
elif isinstance(value, str):
return django_prbac.csv.parse_line(value)
else:
raise ValueError('Invalid value for StringListField: %r is neither the correct type nor deserializable' % value)
[docs] def get_prep_value(self, value):
"""
Converts the value, which must be a string list, to a comma-separated string,
quoted appropriately. This format is private to the field type so it is not
exposed for customization or any such thing.
"""
if not self.is_string_list(value):
raise ValueError('Invalid value for StringListField: %r' % value)
else:
return django_prbac.csv.line_to_string(value, lineterminator='')
[docs] def value_to_string(self, obj):
value = self.value_from_object(obj)
return self.get_prep_value(value)
[docs] def from_db_value(self, value, expression, connection, *args, **kwargs):
return self.to_python(value)
[docs]class StringSetField(StringListField):
"""
A Django field for set of strings.
"""
# TODO thought: If Python had polymorphism this ought be "Serialize a => Field (List a)"
[docs] def is_string_set(self, value):
return isinstance(value, set) and all([isinstance(v, str) for v in value])
[docs] def to_python(self, value):
"""
Best-effort conversion of "any value" to a string set. Mostly strict,
but a bit lenient to allow lists to be passed in by form fields.
"""
# Already the appropriate python type
if self.is_string_set(value):
return value
# If it is a string list, we will turn it into a set; this lenience let's us
# re-use the form field easily
if self.is_string_list(value):
return set(value)
# First let StringListField do whatever it needs to do; this will now be a string list
try:
value = super(StringSetField, self).to_python(value)
except ValueError:
raise ValueError('Invalid value for StringSetField: %r' % value)
return set(value)
[docs] def value_to_string(self, obj):
value = self.value_from_object(obj)
return self.get_prep_value(value)
[docs] def get_prep_value(self, value):
if not self.is_string_set(value):
raise ValueError('Invalid value %r for StringSetField' % value)
else:
return super(StringSetField, self).get_prep_value(sorted(value))
[docs] def from_db_value(self, value, expression, connection, *args, **kwargs):
return self.to_python(value)