Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework, hyperlinking a nested relationship

I've got two models: User and Ticket. Ticket has one User, User has many Tickets

I've accomplished that when i go to url /users/1/tickets, i'm getting the list of user's tickets.

I want to use hyperlinked relations, and here is what i see in my User model representation:

"tickets": [
    "http://127.0.0.1:8000/tickets/5/", 
    "http://127.0.0.1:8000/tickets/6/"
]

But I want it to be like

"tickets": "http://127.0.0.1:8000/users/1/tickets"

Is there a way to do that with DRF?

The url:

    url(r'^users/(?P<user_pk>\d+)/tickets/$',
    views.TicketsByUserList.as_view(),
    name='myuser-tickets'),

The view:

class TicketsByUserList(generics.ListAPIView):
    model = Ticket
    serializer_class = TicketSerializer

    def get_queryset(self):
        user_pk = self.kwargs.get('user_pk', None)
        if user_pk is not None:
            return Ticket.objects.filter(user=user_pk)
        return []

User serializer (i tried to play with tickets field definition, changing type, view_name, but with no effect):

class UserSerializer(serializers.HyperlinkedModelSerializer):
    tickets = serializers.HyperlinkedRelatedField(many=True, view_name='ticket-detail')

    class Meta:
        model = MyUser
        fields = ('id', 'nickname', 'email', 'tickets')

Ticket serializer:

class TicketSerializer(serializers.HyperlinkedModelSerializer):
    user = serializers.HyperlinkedRelatedField(view_name='myuser-detail')
    liked = serializers.Field(source='liked')

    class Meta:
        model = Ticket
        fields = ('id', 'user', 'word', 'transcription', 'translation', 'liked', 'created', 'updated')
like image 733
optimistiks Avatar asked Nov 04 '13 19:11

optimistiks


People also ask

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.

What is hyperlinking in API?

Hyperlinking will generate hyperlink for that field lets say ModelA has ModelB with pk =1. If we hyperlink then there will be link referencing to ModelB like. http://example/api/wdawwawda. that will make ModelB discoverable through link and improve cohesion. i.e. ModelA viewed as whole with valid links instead of pks.

How do you pass extra context data to Serializers in Django REST framework?

In function-based views, we can pass extra context to serializer with “context” parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with “self. context”. From example, to get “exclude_email_list” we just used code 'exclude_email_list = self.

What is hyperlinked relation?

A link relation is a descriptive attribute attached to a hyperlink in order to define the type of the link, or the relationship between the source and destination resources.


1 Answers

You can use a SerializerMethodField to customize it. Something like this:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    tickets = serializers.SerializerMethodField('get_tickets')

    def get_tickets(self, obj):
        return "http://127.0.0.1:8000/users/%d/tickets" % obj.id

    class Meta:
        model = MyUser
        fields = ('id', 'nickname', 'email', 'tickets')

I hard-wired the URL in there for brevity, but you can do a reverse lookup just as well. This basically just tells it to call the get_tickets method instead of the default behavior in the superclass.

like image 71
Joe Holloway Avatar answered Sep 20 '22 07:09

Joe Holloway