How to set absolute url field in serializer model in django rest framework?

I have a model like this:

class GiveAbsolute(serializers.Field):
    def to_native(self,value): 
         # this where it give an error (self doesn't have request)
         # what i want it to give full url 
         # like: http://www.blabla.com/othermodel/1
         return reverse('link_to_othermodel',
                         args=[value],
                         request=self.request)

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

Is there any way to achieve this? thank

+3
source share
3 answers

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

Then, when you already have it in your serializer, you can use self.parent(which is the 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)
+3
source

From source

The request object is a context dictionary entry. i.e.

request = self.context.get('')

:

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

URL

self.request.build_absolute_uri(reverse('some_url_name'))
+8

Based on the answer of the mariodeans, this is a reusable solution for models; I use it to provide service URLs (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)

Usage example

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
+3
source

All Articles