Drdilyor
Drdilyor

Reputation: 1387

How to make all Hyperlinks in Django REST Framework relative?

Is there any easy way to use relative to Root urls instead of absolute ones? By default DRF returns something like this:

{
    "url": "http://127.0.0.1:34503/items/4/",
    ...
    "parent": "http://127.0.0.1:34503/items/1/",
    "stargazers": "http://127.0.0.1:34503/items/4/stargazers",
}

I would like it to be:

{
    "url": "/items/4/",
    ...
    "parent": "/items/1/",
    "stargazers": "/items/4/stargazers",
}

Any ideas?

I am using HyperlinkedModelSerializer:

class ItemSerializer(serializers.HyperlinkedModelSerializer):
    stargazers = serializers.HyperlinkedIdentityField(view_name='item-stargazers')

    class Meta:
        model = Item
        fields = ['url', 'id', ..., 'stargazers']

class ItemViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Item.objects.all().order_by('id')
    serializer_class = ItemSerializer

Upvotes: 4

Views: 700

Answers (2)

Nobody
Nobody

Reputation: 187

The answer from 2021 is still correct, but based on this you can easily make this the default for all your ViewSets.

To create more than one ViewSets with relative urls you subclass viewsets.ModelViewSet:

class RelativeModelViewSet(viewsets.ModelViewSet):
  def get_serializer_context(self):
    result = super().get_serializer_context()
    result['request'] = None
    return(result)

or of course this also works for read only view sets:

class RelativeReadOnlyModelViewSet(viewsets.ReadOnlyModelViewSet):
  def get_serializer_context(self):
    result = super().get_serializer_context()
    result['request'] = None
    return(result)

and then you define your ViewSets as

class ItemViewSet(RelativeReadOnlyModelViewSet):
    queryset = Item.objects.all().order_by('id')
    serializer_class = ItemSerializer

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477265

As the documentation on Absolute and relative URLs states:

If you do want to use relative URLs, you should explicitly pass {'request': None} in the serializer context.

You thus should serialize this with:

class ItemSerializer(serializers.HyperlinkedModelSerializer):
    # …
    
    class Meta:
        model = Account
        fields = ['url', id', 'stargazers']

and then serialize this with:

ItemSerializer(queryset, context={'request', None})

For a ViewSet, you can overide the get_serializer_context method:

class ItemViewSet(viewsets.ReadOnlyModelViewSet):
    # …

    def get_serializer_context(self):
        result = super().get_serializer_context()
        result['request'] = None
        return result

Upvotes: 2

Related Questions