在Django Rest Framework中使用HyperlinkedField进行序列化

时间:2015-07-09 14:59:46

标签: django serialization django-rest-framework

所有

我无法将我的模型的关系字段之一显示为Django Rest Framework中的超链接。 (我正在处理http://www.django-rest-framework.org/api-guide/relations/提供的示例。)这是我的代码:

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)

当我在TrackSerializer中使用SlugRelatedField时,一切都按预期工作。但是当我使用HyperlinkedRelatedField时,我收到以下错误:

  

/ api / tracks /

中的AssertionError      

HyperlinkedRelatedField需要序列化程序上下文中的请求。在实例化序列化程序时添加context={'request': request}

有什么想法吗?

1 个答案:

答案 0 :(得分:7)

正如@zymud所说,您应该将序列化器更改为serializer = AlbumSerializer(album, context={'request': request})AlbumList视图中的AlbumDetail