Files
edx-platform/openedx/core/lib/api/fields.py
Usama Sadiq 068ac5290f refactor: Ran pyupgrade on openedx/core
Ran pyupgrade on openedx/core/{lib, tests}
2021-04-08 18:34:38 +05:00

58 lines
2.2 KiB
Python

"""Fields useful for edX API implementations."""
from rest_framework.serializers import Field, URLField
class ExpandableField(Field): # lint-amnesty, pylint: disable=abstract-method
"""Field that can dynamically use a more detailed serializer based on a user-provided "expand" parameter.
Kwargs:
collapsed_serializer (Serializer): the serializer to use for a non-expanded representation.
expanded_serializer (Serializer): the serializer to use for an expanded representation.
"""
def __init__(self, **kwargs):
"""Sets up the ExpandableField with the collapsed and expanded versions of the serializer."""
assert 'collapsed_serializer' in kwargs and 'expanded_serializer' in kwargs
self.collapsed = kwargs.pop('collapsed_serializer')
self.expanded = kwargs.pop('expanded_serializer')
super().__init__(**kwargs)
def to_representation(self, obj): # lint-amnesty, pylint: disable=arguments-differ
"""
Return a representation of the field that is either expanded or collapsed.
"""
should_expand = self.field_name in self.context.get("expand", [])
field = self.expanded if should_expand else self.collapsed
# Avoid double-binding the field, otherwise we'll get
# an error about the source kwarg being redundant.
if field.source is None:
field.bind(self.field_name, self)
if should_expand:
self.expanded.context["expand"] = set(field.context.get("expand", []))
return field.to_representation(obj)
class AbsoluteURLField(URLField):
"""
Field that serializes values to absolute URLs based on the current request.
If the value to be serialized is already a URL, that value will returned.
"""
def to_representation(self, value):
request = self.context.get('request', None)
assert request is not None, (
"`%s` requires the request in the serializer context. "
"Add `context={'request': request}` when instantiating the serializer." % self.__class__.__name__
)
if value.startswith(('http:', 'https:')):
return value
return request.build_absolute_uri(value)