Django按多对多关联用户分类筛选分组并仅返回符合条件的用户
解决方法
你之前的filter操作仅过滤了「包含指定分类用户的分组」,没有对分组下关联的用户集合做过滤,需要显式对关联的用户查询集做筛选,有两种常用实现方案:
方案1:使用Prefetch预取过滤后的用户(推荐,无N+1查询问题)
通过Django自带的Prefetch对象可以在查询分组时,提前把符合分类要求的用户预取到分组属性中,性能最优:
from django.db.models import Prefetch # 先获取目标分类 target_category = Category.objects.get(pk=category_id) # 定义过滤后的用户查询集 filtered_user_qs = User.objects.filter(category_id=target_category.id) # 查询分组+预取过滤后的用户 group_qs = Group.objects.filter( user__category_id=target_category.id ).prefetch_related( Prefetch('user_set', queryset=filtered_user_qs, to_attr='matched_users') ).distinct()
后续序列化时直接读取分组的matched_users属性即可,该属性仅包含分类匹配的用户。如果你的User模型多对多字段自定义了related_name,请将代码中的user_set替换为你设置的related_name值。
如果使用DRF序列化,序列化器配置示例如下:
class GroupSerializer(serializers.ModelSerializer): users = UserSerializer(source='matched_users', many=True) class Meta: model = Group fields = ('id', 'users', ) # 补充其他你需要返回的字段
方案2:序列化时动态过滤(适合小数据量场景)
如果数据量很小,可以直接在序列化器中通过SerializerMethodField动态过滤用户,实现更简单:
class GroupSerializer(serializers.ModelSerializer): users = serializers.SerializerMethodField() def get_users(self, obj): # 从序列化上下文获取传入的分类ID category_id = self.context.get('category_id') matched_users = obj.user_set.filter(category_id=category_id) return UserSerializer(matched_users, many=True).data class Meta: model = Group fields = ('id', 'users', ) # 补充其他你需要返回的字段
调用序列化时需要把分类ID传入上下文:
serializer = GroupSerializer(group_qs, many=True, context={'category_id': category_id})
该方案在分组数量较多时会产生N+1查询问题,仅建议小数据量场景使用。
内容的提问来源于stack exchange,提问作者ndyr
相关产品推荐
相关产品推荐

