Problem
I have a model with the following standard generic foreign key fields:
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
event_object = generic.GenericForeignKey('content_type', 'object_id')
According to REST framework's docs, I can do the following to serialise this correctly:
class WhateverSerializer(serializers.ModelSerializer):
event_object = serializers.RelatedField(source='event_object')
This works fine, however in two other related situations, I can't get things working:
HyperlinkedRelatedField
. This field requires the view_name argument, something I can't declare since the view name varies with the related model. I solved this by using SerializerMethodField
, instantiating a HyperlinkedIdentityField
at runtime and returning its field_to_native
method (see snippet below). This does not feel very elegant.event_object = SoAndSoSerializer(source='event_object')
. The only solution I can see is to walk every *Serializer
I have defined and check which has the correct model, then use that. Again, this does not feel very elegant.Questions
is HyperlinkRelatedField meant to work across a generic relationship? Am I just making a mistake? Is there an obvious solution to picking the right *Serializer
that I'm missing?
Code Snippet
The inelegant solution mentioned in bullet point 1 above:
class WhateverSerializer(DefaultSerializer):
event_object_url = serializers.SerializerMethodField('get_related_object_url')
# ...
def get_related_object_url(self, obj):
obj = obj.event_object
default_view_name = '%(model_name)s-detail'
format_kwargs = {
'app_label': obj._meta.app_label,
'model_name': obj._meta.object_name.lower()
}
view_name = default_view_name % format_kwargs
s = serializers.HyperlinkedIdentityField(source=obj, view_name=view_name)
s.initialize(self, None)
return s.field_to_native(obj, None)
Django is the web development framework in python whereas the Django Rest Framework is the library used in Django to build Rest APIs. Django Rest Framework is especially designed to make the CRUD operations easier to design in Django. Django Rest Framework makes it easy to use your Django Server as an REST API.
APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.
Django Rest Framework makes it easy to use your Django Server as an REST API. REST stands for "representational state transfer" and API stands for application programming interface.
Your right, REST framework doesn't support those use cases, and its not obvious to me what the design would look like if it did. You'd probably need an implicit registry of model->view (for the hyperlinked case) and model-> serializer (for the nested case) which I don't think I'd be very keen on.
The simplest way to do what you need is probably to subclass ManyRelatedField
and create a custom field type, overriding to_native(self, obj)
to serialize each object in the set exactly the way you want it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With