15

嗨,我是 Django 和 Django-Rest-Framework 的新手。我已经完成了教程。我正在尝试做的(作为学习练习)是根据主键以外的字段返回一个对象。

  • myserver:8000/videos返回所有视频的列表。
  • myserver:8000/videos/1返回主键为 1 的视频

我想做的是:

  • myserver:8000/videos/:videoname返回视频在哪里videoname = videoname

我有以下视频模型:

class Videos (models.Model):
    videoID = models.IntegerField(blank=True, null=True)
    videoName = models.CharField(max_length=20)
    class Meta:
        app_label="quickstart"

我的路由器配置为:

video_detail = views.VideoDetailView.as_view({
    'get':'list'
})

urlpatterns = patterns('',
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^videos/(?P<videoName>[^/]+)/$', video_detail)
)

我的观点被定义为:

class VideoDetailView(viewsets.ModelViewSet):
    serializer_class = VideosSerializer
    def get_queryset(self):
        videoName = self.kwargs.get(videoName, None)
        queryset = super (VideoDetailView,self).get_queryset()
        if videoName:
            queryset = queryset.filter(videoName=videoName)
        return queryset

api 运行,但是当我点击:(myserver:8000/videos/SecondVideo/其中“SecondVideo”是视频的名称)时,我收到 404 错误。

有什么帮助吗?

4

5 回答 5

17

尝试lookup_field在您的视图类上设置属性。该字段将用于查找单个模型实例。它默认为,'pk'但您可以将其更改为'videoName'.

class VideoDetailView(viewsets.ModelViewSet):
    serializer_class = VideosSerializer
    lookup_field = 'videoName'
于 2013-10-15T21:10:55.773 回答
11

所以我想通了。发生的事情是

router.register(r'videos', views.VideosViewSet)

正在处理myserver:8000/videos/1,因此我的新 url 模式 url(r'^videos/(?P<videoName>.+)/$', views.VideoDetailView.as_view())被注册的路由覆盖。有效的代码是:

urls.py

url(r'^video/(?P<videoName>.+)/$', views.VideoDetailView.as_view())

views.py

class VideoDetailView(generics.ListAPIView):
    serializer_class = VideosSerializer

    def get_queryset(self):
        videoName = self.kwargs['videoName']
        return Videos.objects.filter(videoName=videoName)

这个关于过滤 URL 的文档页面帮助我拼凑出正在发生的事情。

于 2013-10-17T17:54:50.300 回答
3

像这样的解决方案怎么样:

视图.py

class VideoDetailView(generics.RetrieveAPIView):
    serializer_class = VideosSerializer
    lookup_field = 'videoName'

推理:你想要一个detailview,所以不需要ListViewbutRetriveAPIView

如果需要一些进一步的操作,只需覆盖get_object这样的方法:

def get_object(self):
    obj = super(VideoDetailView, self).get_object()
    # perform some extra checks on obj, e.g custom permissions
    return obj
于 2016-01-07T10:44:50.327 回答
2

使用ModelViewSets ,您可以使用@action装饰器,如果您不想更改视图集和序列化程序的完整查找行为,则可以定义特定方法。例如:

class VideoDetailView(viewsets.ModelViewSet):
    queryset = Videos.objects.all()
    serializer_class = VideosSerializer

    @action(detail=True)
    def video_name(self, request, pk=None):
        queryset = Video.objects.get(videoName=pk) # pk will be the video name
        serializer = VideosSerializer(queryset, many=True) # You can specify other serializer if you want here
        return Response(serializer.data)

然后,您的网址将是:myserver:8000/videos/SecondVideo/video_name/

您可以阅读更多内容:https ://www.django-rest-framework.org/api-guide/viewsets/

于 2019-03-27T21:32:32.930 回答
2

信用https://www.youtube.com/watch?v=dWZB_F32BDg

使用lookup_field定义查询表使用的字段,使用look_up_kwargs定义url中的字段

url(r'^videos/(?P<videoName>[^/]+)/$', video_detail)

class VideoDetailView(viewsets.ModelViewSet):
    serializer_class = VideosSerializer
    queryset = Videos.objects.all()
    lookup_field = 'videoName'
    lookup_url_kwarg = 'videoName'
于 2017-08-02T13:33:39.490 回答