Newer
Older
def __init__(self, name, allow_all=False, qs_filter=None):
self.name = name
self.allow_all = allow_all
self.qs_filter = qs_filter
def __repr__(self):
return "<Action {}>".format(self.name)
class ActionSerializer(serializers.Serializer):
"""
A special serializer that can operate on a list of objects
and apply actions on it.
"""
action = serializers.CharField(required=True)
objects = serializers.JSONField(required=True)
filters = serializers.DictField(required=False)
actions = None
def __init__(self, *args, **kwargs):
self.actions_by_name = {a.name: a for a in self.actions}
"You must declare a list of actions on " "the serializer class"
)
for action in self.actions_by_name.keys():
handler_name = "handle_{}".format(action)
assert hasattr(self, handler_name), "{} miss a {} method".format(
self.__class__.__name__, handler_name
)
super().__init__(self, *args, **kwargs)
def validate_action(self, value):
try:
return self.actions_by_name[value]
except KeyError:
value, ", ".join(self.actions_by_name.keys())
)
)
def validate_objects(self, value):
if value == "all":
return self.queryset.all().order_by("id")
return self.queryset.filter(pk__in=value).order_by("id")
"{} is not a valid value for objects. You must provide either a "
'list of identifiers or the string "all".'.format(value)
)
allow_all = data["action"].allow_all
if not allow_all and self.initial_data["objects"] == "all":
Eliot Berriot
committed
raise serializers.ValidationError(
"You cannot apply this action on all objects"
final_filters = data.get("filters", {}) or {}
if self.filterset_class and final_filters:
qs_filterset = self.filterset_class(final_filters, queryset=data["objects"])
try:
assert qs_filterset.form.is_valid()
except (AssertionError, TypeError):
raise serializers.ValidationError("Invalid filters")
data["objects"] = qs_filterset.qs
if data["action"].qs_filter:
data["objects"] = data["action"].qs_filter(data["objects"])
data["count"] = data["objects"].count()
if data["count"] < 1:
raise serializers.ValidationError("No object matching your request")
handler_name = "handle_{}".format(self.validated_data["action"].name)
"action": self.validated_data["action"].name,