funkwhale/api/funkwhale_api/common/preferences.py

108 wiersze
2.7 KiB
Python

import json
from django import forms
from django.conf import settings
from django.contrib.postgres.forms import JSONField
from dynamic_preferences import serializers, types
from dynamic_preferences.registries import global_preferences_registry
class DefaultFromSettingMixin:
def get_default(self):
return getattr(settings, self.setting)
def get(pref):
manager = global_preferences_registry.manager()
return manager[pref]
def all():
manager = global_preferences_registry.manager()
return manager.all()
def set(pref, value):
manager = global_preferences_registry.manager()
manager[pref] = value
class StringListSerializer(serializers.BaseSerializer):
separator = ","
sort = True
@classmethod
def to_db(cls, value, **kwargs):
if not value:
return
if type(value) not in [list, tuple]:
raise cls.exception(
f"Cannot serialize, value {value} is not a list or a tuple"
)
if cls.sort:
value = sorted(value)
return cls.separator.join(value)
@classmethod
def to_python(cls, value, **kwargs):
if not value:
return []
return value.split(",")
class StringListPreference(types.BasePreferenceType):
serializer = StringListSerializer
field_class = forms.MultipleChoiceField
def get_api_additional_data(self):
d = super().get_api_additional_data()
d["choices"] = self.get("choices")
return d
class JSONSerializer(serializers.BaseSerializer):
required = True
@classmethod
def to_db(cls, value, **kwargs):
if not cls.required and value is None:
return json.dumps(value)
data_serializer = cls.data_serializer_class(data=value)
if not data_serializer.is_valid():
raise cls.exception(
f"{value} is not a valid value: {data_serializer.errors}"
)
value = data_serializer.validated_data
try:
return json.dumps(value, sort_keys=True)
except TypeError:
raise cls.exception(
f"Cannot serialize, value {value} is not JSON serializable"
)
@classmethod
def to_python(cls, value, **kwargs):
return json.loads(value)
class SerializedPreference(types.BasePreferenceType):
"""
A preference that store arbitrary JSON and validate it using a rest_framework
serializer
"""
serializer = JSONSerializer
data_serializer_class = None
field_class = JSONField
widget = forms.Textarea
@property
def serializer(self):
class _internal(JSONSerializer):
data_serializer_class = self.data_serializer_class
required = self.get("required")
return _internal