-
-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP Enhance relation field serialization for image content types #1442
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
- Enhance relation field serialization for image content types [@reebalazs] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
from plone.dexterity.interfaces import IDexterityContent | ||
from plone.restapi.interfaces import IRelationObjectSerializer | ||
from plone.restapi.serializer.converters import json_compatible | ||
from zope.component import adapter | ||
from zope.component import getMultiAdapter | ||
from zope.interface import implementer | ||
from zope.interface import Interface | ||
from zope.interface import alsoProvides | ||
from plone.app.contenttypes.interfaces import IImage | ||
from plone.namedfile.interfaces import INamedImageField | ||
from z3c.relationfield.interfaces import IRelationChoice | ||
|
||
import logging | ||
|
||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
@adapter(IDexterityContent, IRelationChoice, IDexterityContent, Interface) | ||
@implementer(IRelationObjectSerializer) | ||
class DefaultRelationObjectSerializer: | ||
def __init__(self, rel_obj, field, context, request): | ||
self.context = context | ||
self.request = request | ||
self.field = field | ||
self.rel_obj = rel_obj | ||
|
||
def __call__(self): | ||
obj = self.rel_obj | ||
# Start from the values of the default field serializer | ||
result = json_compatible(self.get_value()) | ||
if result is None: | ||
return None | ||
# Add some more values from the object in relation | ||
additional = { | ||
"id": obj.id, | ||
"created": obj.created(), | ||
"modified": obj.modified(), | ||
"UID": obj.UID(), | ||
} | ||
result.update(additional) | ||
return json_compatible(result) | ||
|
||
def get_value(self, default=None): | ||
return getattr(self.field.interface(self.context), self.field.__name__, default) | ||
|
||
|
||
class FieldSim: | ||
def __init__(self, name, provides): | ||
self.__name__ = name | ||
alsoProvides(self, provides) | ||
|
||
def get(self, context): | ||
return getattr(context, self.__name__) | ||
|
||
|
||
class FieldRelationObjectSerializer(DefaultRelationObjectSerializer): | ||
"""The relationship object is treatable like a field | ||
|
||
So we can reuse the serialization for that specific field. | ||
""" | ||
|
||
field_name = None | ||
field_interface = None | ||
|
||
def __call__(self): | ||
field = FieldSim(self.field_name, self.field_interface) | ||
result = super().__call__() | ||
if result is None: | ||
return None | ||
# Reuse a serializer from dxfields | ||
serializer = getMultiAdapter((field, self.rel_obj, self.request)) | ||
# Extend the default values with the content specific ones | ||
additional = serializer() | ||
if additional is not None: | ||
result.update(additional) | ||
return result | ||
|
||
|
||
@adapter(IImage, IRelationChoice, IDexterityContent, Interface) | ||
class ImageRelationObjectSerializer(FieldRelationObjectSerializer): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting approach, wondering how this will scale in the case that we have a custom content type and we want to return, let's say two images. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or a combination of fields. Not sure if make a 1:1 content type => field serialised I would like to include in the final serialization is a good choice. |
||
# The name of the attribute that contains the data object within the relation object | ||
field_name = "image" | ||
# The field adapter that we will emulate to get the serialized data for this content type | ||
field_interface = INamedImageField |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't really need to tie this to the plone.volto change. So I'd remove this for the merge.