Reputation: 4504
All,
I am having trouble making one of my model's relational fields show up as a hyperlink in Django Rest Framework. (I am working off of the examples provided at http://www.django-rest-framework.org/api-guide/relations/.) Here is my code:
models.py:
class Album(models.Model):
album_name = models.CharField(max_length=100)
artist = models.CharField(max_length=100)
class Track(models.Model):
album = models.ForeignKey(Album, related_name='tracks')
order = models.IntegerField()
title = models.CharField(max_length=100)
duration = models.IntegerField()
class Meta:
unique_together = ('album', 'order')
ordering = ['order']
def __unicode__(self):
return '%d: %s' % (self.order, self.title)
serializers.py:
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.StringRelatedField(many=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
class TrackSerializer(serializers.ModelSerializer):
# THIS WORKS...
# album = serializers.SlugRelatedField(slug_field="album_name", read_only=True)
# THIS DOES NOT WORK...
album = serializers.HyperlinkedRelatedField(view_name="album-detail", read_only=True)
class Meta:
model = Track
fields = ('album', 'order', 'title', 'duration')
views.py:
@api_view(('GET',))
def api_root(request, format=None):
return Response({
'albums': reverse("album-list", request=request, format=format),
'tracks': reverse("track-list", request=request, format=format),
})
class AlbumList(APIView):
def get(self, request, format=None):
albums = Album.objects.all()
serializer = AlbumSerializer(albums, many=True)
return Response(serializer.data)
def post(self, request, format=None):
album = AlbumSerializer(data=request.data)
if album.is_valid():
album.save()
return Response(album.data, status=status.HTTP_201_CREATED)
else:
return Response(album.errors, status=status.HTTP_400_BAD_REQUEST)
class AlbumDetail(APIView):
def get_object(self, pk):
try:
return Album.objects.get(pk=pk)
except Album.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
album = self.get_object(pk)
serializer = AlbumSerializer(album)
return Response(serializer.data)
def put(self, request, pk, format=None):
album = self.get_object(pk)
serializer = AlbumSerializer(album, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
album = self.get_object(pk)
album.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class TrackList(APIView):
def get(self, request, format=None):
tracks = Track.objects.all()
serializer = TrackSerializer(tracks, many=True)
return Response(serializer.data)
def post(self, request, format=None):
track = TrackSerializer(data=request.data)
if track.is_valid():
track.save()
return Response(track.data, status=status.HTTP_201_CREATED)
else:
return Response(track.errors, status=status.HTTP_400_BAD_REQUEST)
class TrackDetail(APIView):
def get_object(self, pk):
try:
return Track.objects.get(pk=pk)
except Track.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
track = self.get_object(pk)
serializer = TrackSerializer(track)
return Response(serializer.data)
def put(self, request, pk, format=None):
track = self.get_object(pk)
serializer = TrackSerializer(track, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
track = self.get_object(pk)
track.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
urls.py:
urlpatterns = patterns('',
url(r'^api/$', api_root),
url(r'^api/albums/$', AlbumList.as_view(), name="album-list"),
url(r'^api/albums/(?P<pk>[0-9]+)/$', AlbumDetail.as_view(), name="album-detail"),
url(r'^api/tracks/$', TrackList.as_view(), name="track-list"),
url(r'^api/tracks/(?P<pk>[0-9]+)/$', TrackDetail.as_view(), name="track-detail"),
)
urlpatterns = format_suffix_patterns(urlpatterns)
When I use the SlugRelatedField in the TrackSerializer, everything works as expected. But when I use the HyperlinkedRelatedField, I get the following error:
AssertionError at /api/tracks/
HyperlinkedRelatedField
requires the request in the serializer context. Addcontext={'request': request}
when instantiating the serializer.
Any thoughts?
Upvotes: 2
Views: 5021
Reputation: 2572
As @zymud said, you should change the serializer to serializer = AlbumSerializer(album, context={'request': request})
in the AlbumList
and AlbumDetail
views
Upvotes: 8