[Django]-How to put absolute url field in serializer model in django rest framework?

3πŸ‘

βœ…

The only thing in DRF, that has an access to request object is the view, so you need to figure out how to pass your request from view to serializer, for example in generic ListView you can use get_serializer.

Then, when you already have it in your serializer, you can use self.parent (which is a parent serializer) to capture it from the field itself:

class GiveAbsolute(serializers.Field):
    def to_native(self,value):
        return reverse('link_to_othermodel',
                     args=[value],
                     request=self.parent.request)


class SomethingSerializer(serializers.ModelSerializer):
    # field with foreign key
    othermodel = GiveAbsolute(source="othermodel.id")
    class Meta:
        model=Something
        fields=("fields1","othermodel")

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(SomethingSerializer, self).__init__(*args, **kwargs)


class SomethingView(generics.ListAPIView):
    model = Something
    serializer_class = SomethingSerializer

    def get_serializer(self, instance=None, data=None,
                   files=None, many=False, partial=False):

        serializer_class = self.get_serializer_class()
        context = self.get_serializer_context()
        return serializer_class(instance, data=data, files=files, many=many,
                                partial=partial, context=context, request=self.request)
πŸ‘€mariodev

8πŸ‘

From the source

The request object is an entry of the context dictionary. ie.

request = self.context.get(β€˜request’)

In your case, just do:

self.request = self.context.get('request')

then build the url

self.request.build_absolute_uri(reverse('some_url_name'))
πŸ‘€Kwaw Annor

4πŸ‘

Based on the answer of mariodev, here is a reusable solution for Models ; I use it to provide URLs to service (see them as metheds) on django models.

Reusable components

serializers.py

class RequestAwareSerializer(serializers.ModelSerializer):
    """
    A serializer which fields can access the request object.
    """
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(RequestAwareSerializer, self).__init__(*args, **kwargs)

class APIMethodField(serializers.Field):
    """ To get the absolute URL of a method accessible via the API
    """
    def __init__(self, url_action_name, *args, **kwargs):
        self._url_name = url_action_name
        super(APIMethodField, self).__init__(source='*', *args, **kwargs)

    def to_native(self, obj):
        """
        @param objid the ID of the object
        @param method_url_name, the name of the url, as in urls.py
        """
        return reverse_lazy(self._url_name, args=[obj.id],


                   request=self.parent.request)

views.py

class ChattyModelViewSet(ModelViewSet):
    """ ModelViewSet which informs the serializer about the request

    (abstract)
    """
    def get_serializer(self, instance=None, data=None,
                   files=None, many=False, partial=False):

        serializer_class = self.get_serializer_class()
        context = self.get_serializer_context()
        return serializer_class(instance, data=data, files=files, many=many,
                                partial=partial, context=context,
                                request=self.request)

Example use

urls.py

url(r'^v1/maildomain/(?P<maildomain_id>\d+)/check/$',
    views.MailDomainDetail.as_view(), name='maildomain_dns_check')

serializers.py

class MailDomainSerializer(RequestAwareSerializer):
    checkdns_url = APIMethodField(url_action_name='maildomain_dns_check')

    class Meta:
        model = MailDomain()
        fields = ('name', 'checkdns_url')

views.py

class MailDomainView(ChattyModelViewSet):
    model = MailDomain
    serializer_class = MailDomainSerializer

Leave a comment