Python 使用Django REST框架定义过滤端点的更好方法
我在用户和图像之间建立了一种关系,每个用户都可以有多个图像。我需要定义一个端点来检索特定用户的所有图像:Python 使用Django REST框架定义过滤端点的更好方法,python,django,django-rest-framework,Python,Django,Django Rest Framework,我在用户和图像之间建立了一种关系,每个用户都可以有多个图像。我需要定义一个端点来检索特定用户的所有图像: GET/users/:id/images 我是这样做的: url.py router = routers.DefaultRouter() router.register(r'images', ImageViewSet) image_list = ImageViewSet.as_view({ 'get': 'list' }) urlpatterns = patterns('',
GET/users/:id/images
我是这样做的:
url.py
router = routers.DefaultRouter()
router.register(r'images', ImageViewSet)
image_list = ImageViewSet.as_view({
'get': 'list'
})
urlpatterns = patterns('',
...
url(r'^', include(router.urls)),
url(r'^users/(?P<user_id>[^/]+)/images/$', image_list),
...
)
class ImageViewSet(viewsets.ModelViewSet):
queryset = Image.objects.all()
serializer_class = ImageSerializer
def get_queryset(self):
user_id = self.kwargs.get('user_id', None)
if user_id:
return Image.objects.filter(user_id=user_id)
return super(ImageViewSet, self).get_queryset()
它很管用,但我不满意。想象一些类似于
/users/:user\u id/images/
的附加端点,即类似于/categories/:categories\u id/images/
等的端点。将获取查询集作为这两个端点的入口点,让它基于夸尔格来区分它们,似乎不是很吸引人。有更好的方法吗 在基本情况下,您最终指定了一个模型和一个序列化程序类。没有理由不将这两种方法都放在某种表中,并使用kwargs
进行查找
LOOK_UP_TABLE = {
'users' : {
'model': ...,
'serializer_class': ...,
},
'categories' : {
...
},
}
如果您这样做了,并且覆盖了get\u queryset
,那么您也可以覆盖get\u serializer\u class
。然后你会有一些非常普通的东西
我不知道你到底能节省多少打字(特别是如果你使用编辑器的代码片段功能)。或者由此产生的系统会有多灵活。但这是一个有趣的想法。在基本情况下,您最终指定了一个模型和一个序列化器类。没有理由不将这两种方法都放在某种表中,并使用kwargs
进行查找
LOOK_UP_TABLE = {
'users' : {
'model': ...,
'serializer_class': ...,
},
'categories' : {
...
},
}
如果您这样做了,并且覆盖了get\u queryset
,那么您也可以覆盖get\u serializer\u class
。然后你会有一些非常普通的东西
我不知道你到底能节省多少打字(特别是如果你使用编辑器的代码片段功能)。或者由此产生的系统会有多灵活。但是这是一个有趣的想法。你真的应该在get\u queryset()
中使用super()
来获取未过滤的查询集,然后根据kwargs
对其进行过滤
if user_id:
super(ImageViewSet, self).get_queryset().filter(user_id=user_id)
您会注意到,这变得非常通用,可以作为mixin包含在每个视图中:
class FilterByUserMixin(object):
def get_queryset(self):
user_id = self.kwargs.get('user_id', None)
queryset = super(FilterByUserMixin, self).get_queryset()
if user_id:
queryset = queryset.filter(user_id=user_id)
return querset
class ImageViewSet(FilterByUserMixin, viewsets.ModelViewSet):
queryset = Image.objects.all()
serializer_class = ImageSerializer
class CategoryViewSet(FilterbyUserMixin, viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
您确实应该在get\u queryset()
中使用super()
来获取未筛选的查询集,并根据kwargs
对其进行筛选
if user_id:
super(ImageViewSet, self).get_queryset().filter(user_id=user_id)
您会注意到,这变得非常通用,可以作为mixin包含在每个视图中:
class FilterByUserMixin(object):
def get_queryset(self):
user_id = self.kwargs.get('user_id', None)
queryset = super(FilterByUserMixin, self).get_queryset()
if user_id:
queryset = queryset.filter(user_id=user_id)
return querset
class ImageViewSet(FilterByUserMixin, viewsets.ModelViewSet):
queryset = Image.objects.all()
serializer_class = ImageSerializer
class CategoryViewSet(FilterbyUserMixin, viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
你的意思是你必须定义url的方式?应用程序怎么知道在哪里提供服务呢?我的一个想法是在UserViewSet中添加一个images操作,用@link装饰它,然后在ImageViewSet中重用get操作。自从提出这个问题以来,我尝试过这样做,但这似乎不是一件很容易的事情。而且,考虑了更多,手动定义url对我来说一点也不麻烦,就像必须以这种方式弄脏get_queryset方法一样。想象一下,有一些类似于/users/:id/images
的附加端点,类似于/category/:category\u id/images
等,将get\u queryset作为所有这些端点的入口点似乎是个坏主意。你是说一种必须定义url的方式吗?应用程序怎么知道在哪里提供服务呢?我的一个想法是在UserViewSet中添加一个images操作,用@link装饰它,然后在ImageViewSet中重用get操作。自从提出这个问题以来,我尝试过这样做,但这似乎不是一件很容易的事情。而且,考虑了更多,手动定义url对我来说一点也不麻烦,就像必须以这种方式弄脏get_queryset方法一样。想象一下,有一些类似于/users/:id/images
的附加端点,类似于/category/:category\u id/images
等,将get\u queryset作为所有这些端点的入口点似乎是个坏主意。