Django SortedManyToManyField按指定分类调整商品排序实现问题
解决Django sortedm2m指定分类下商品排序的核心逻辑
sortedm2m的
SortedManyToManyField会自动创建多对多中间表,每个「分类-商品」的关联记录都有独立的sort_value排序字段,所以只要修改指定分类对应关联记录的排序值,就不会影响同一商品在其他分类下的排序。
核心实现方案
有两种常用实现方式,可根据业务需求选择:
方案1:直接操作中间表(推荐,灵活度高)
直接更新指定分类和商品对应关联的排序值,不会删除不在传入列表中的商品关联,适合局部调整排序的场景,完善后的视图代码如下:
from django.shortcuts import get_object_or_404 from .models import Category, Product class ProductViewSet(ModelViewSet): @transaction.atomic @action(methods=["put"], detail=False) def order(self, request): """ 该接口接收商品ID列表和分类ID,修改指定分类下的商品排序 # products = [2, 8, 4, 22] # category = 'xyz' """ serializer = ProductOrderingSerializer(data=request.data) serializer.is_valid(raise_exception=True) product_id_list = serializer.validated_data["products"] # 先校验分类是否存在 category = get_object_or_404(Category, id=serializer.validated_data["category"]) # 获取sortedm2m自动生成的中间表模型 SortThroughModel = Product.categories.through for index, product_id in enumerate(product_id_list): # 仅更新指定分类+指定商品对应关联的排序值 SortThroughModel.objects.filter( category_id=category.id, product_id=product_id ).update(sort_value=index) self.action = "list" return self.list(request=request)
方案2:使用反向关系的set方法
如果传入的products列表是该分类下全部商品的最终排序结果,可以直接用sortedm2m提供的关系管理器set方法,会自动按传入顺序设置排序值,不在列表中的商品会被移除出该分类:
# 仅需替换核心逻辑部分 category = get_object_or_404(Category, id=serializer.validated_data["category"]) # 直接按传入的商品ID顺序设置分类下的关联,自动更新排序 category.product_items.set(serializer.validated_data["products"])
效果验证
按照你给出的业务场景测试:
- 传入
products=[p2.id, p1.id]和分类x的ID,只会更新分类x对应的关联记录的sort_value - 分类y下的关联记录完全没有修改,排序保持
p1、p2不变,完全符合预期
内容的提问来源于stack exchange,提问作者coredumped0x
相关产品推荐
相关产品推荐

