按主键以外的字段获取对象

时间:2013-10-15 17:00:13

标签: django django-rest-framework

嗨,我是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错误。

任何帮助?

5 个答案:

答案 0 :(得分:10)

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

class VideoDetailView(viewsets.ModelViewSet):
    serializer_class = VideosSerializer
    lookup_field = 'videoName'

答案 1 :(得分:9)

所以我明白了。

是怎么回事
router.register(r'videos', views.VideosViewSet)

正在处理myserver:8000/videos/1,因此注册路线会覆盖我的新网址格式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过滤的documentation page帮助我拼凑了正在发生的事情。

答案 2 :(得分:3)

这样的解决方案怎么样:

views.py

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

推理: 您需要详细视图,因此不需要ListViewRetriveAPIView

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

def get_object(self):
    obj = super(VideoDetailView, self).get_object()
    # perform some extra checks on obj, e.g custom permissions
    return obj

答案 3 :(得分:0)

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

使用 lookup_field 定义用于查询表格的字段,并使用 look_up_kwargs 为网址中的字段

<div> <h2>Title</h2> <div class="info_row"> <div>Category:</div> <div>data</div> </div> </div>

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

答案 4 :(得分:0)

使用 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/