Support for expandable `SerializerMethodFields`
J-Priebe opened this issue · 3 comments
Hello, I have a few large SerializerMethodFields
on my serializer, which return iterables that are not a FK to my model. Something like this:
Class FooSerializer(FlexFieldsModelSerializer):
things = SerializerMethodField()
def get_things(self, instance):
return ThingSerializer(get_things_related_to_this_instance(instance), many=True).data
As far as I know I cannot directly leverage drf-flex-fields
to make this field expandable, because expandable_fields
are a statically defined dict that takes a serializer class or tuple.
I have hacked around this by making these fields omitted by default, unless declared in the expand
argument:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
expandable_method_fields = ('things', 'more_things')
if '~all' in self._flex_options['expand'] or '*' in self._flex_options['expand']:
return
for field in expandable_method_fields:
if (
field not in self._flex_options['expand']
and field not in self._flex_options['omit']
):
self._flex_options['omit'].append(field)
It works well enough for my purposes, but I thought I'd pitch this as a feature request, in case it is helpful or others have solved the problem differently. Cheers, and thanks for the library!
I like the idea of supporting DRF's SerializerMethodField
as an expandable field. One thing, though, is that it doesn't take keyword arguments for expand
, omit
, fields
. This would only matter if you wanted dynamic behavior within that method.
class UserSerializer(serializers.ModelSerializer):
friends = HyperlinkFIeld()
class Meta:
model = User
expandable_fields = {'friends': serializer.SerializerMethodField}
def get_friends(self, obj, expand, fields, omit):
# serialize friends using custom logic
We could add a custom FlexSerializerMethodField
- a subclass of SerializerMethodField that accepts those keyword arguments. Another possibility is making it a little smarter so it doesn't try to pass the keyword arguments if the expanded field is an instance of SerializerMethodField
.
Is it not possible to do something like:
FooSerializer.Meta.exclude = ("friends", )
and ask for it in query params if we want it/route?fields=friends
?
I think this breaks the model of expanding a field. Getting back the non expanded version of friends
is different from not getting anything at all. I really like the idea of having something like FlexSerializerMethodField
as @rsinger86 mentioned. Are there any plans on getting something like this implemented?
One workaround that I've used is to convert your method field to an annotation on the queryset and expand on that. It also has the benefit of being much faster in most cases.