如何规范组织Django REST Framework路由及API实现疑问
Django REST Framework 电商API设计疑问解答
我正在基于Django(DRF)开发一个电商演示应用,对如何编写优质REST API存在一些困惑。
模型代码
class Category(models.Model): name = models.CharField(...) class Product(models.Model): category = models.ForeignKey(Category, ...) name = models.CharField(...)
当前视图代码
class ProductListView(APIView): def get(self, request, category_slug=None): products = Product.objects.filter(available=True) if category_slug: category = get_object_or_404(Category, slug=category_slug) products = products.filter(category=category) serializer = ProductSerializer(products, many=True) return Response(serializer.data, status=status.HTTP_200_OK)
问题一:是否应将基于category_slug的过滤逻辑放在当前视图中,还是拆分为两个端点更清晰?
两种方案各有适用场景,具体可以参考:
- 保留当前视图:如果“查询全部商品”和“按分类查询商品”属于同一资源(商品)的不同过滤场景,当前的实现是合理的。REST风格中,路径参数可用于资源的细分过滤,这种写法语义清晰,也减少了端点数量。你还可以用
django-filter简化过滤逻辑,替代手写的if判断,让代码更简洁:# 示例:用django-filter实现分类过滤 from django_filters.rest_framework import FilterSet, filters class ProductFilter(FilterSet): category_slug = filters.CharFilter(field_name='category__slug') class Meta: model = Product fields = ['category_slug'] # 视图改用GenericAPIView+ListModelMixin class ProductListView(generics.ListAPIView): queryset = Product.objects.filter(available=True) serializer_class = ProductSerializer filterset_class = ProductFilter - 拆分为两个端点:如果后续分类相关的商品逻辑会扩展(比如需要返回分类的额外信息、分类专属的排序规则),或者客户端更倾向于语义化的路径(比如
/categories/{slug}/products/),拆分端点会更清晰。这种写法把“分类下的商品”作为分类资源的子资源,符合REST的资源层级设计。
问题二:在DRF中,单个端点返回多组数据是否属于最佳实践?
没有绝对的标准答案,核心看数据的关联程度:
- 不建议合并的场景:如果两组数据是完全独立的资源(比如商品列表和全局分类列表),拆分端点更合适。这样符合单一职责原则,客户端可以按需请求,也更利于缓存和后续维护(比如修改其中一组数据的逻辑时,不会影响另一组)。
- 建议合并的场景:如果两组数据强关联(比如查询分类下的商品时,同时返回该分类的名称、描述;或者返回商品列表+分页元数据),合并返回能减少客户端的请求次数,提升用户体验。此时要注意明确响应结构,用清晰的键名替代模糊的
data/other_data,比如:# 示例:返回分类信息+商品列表 return Response({ 'category': CategorySerializer(category).data, 'products': serializer.data }, status=status.HTTP_200_OK)
内容的提问来源于stack exchange,提问作者Jože Kuhar
相关产品推荐
相关产品推荐

