You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django如何使用用户存储的分类列表正确筛选Poller查询集?

问题根因

你存储用户选择的分类时,使用json.dumps()将分类列表序列化为了JSON字符串存入categories_selected字段,因此查询时取出的字段值不是Python列表,而是带方括号、引号的JSON格式字符串(比如你打印看到的['category_foo']实际是字符串"[\"category_foo\"]"),直接用这个字符串去匹配Category的category字段自然找不到结果,之前的Q对象写法失效也是同一个原因。

修复方案

取出分类配置后先做JSON反序列化,再执行查询即可:

import json

def render_random_poller(request):
    if request.user.is_authenticated:
        # 获取用户的分类筛选配置,不存在则创建默认空配置
        user_filter, _ = UserCategoryFilter.objects.get_or_create(user=request.user)
        # 反序列化JSON字符串得到分类名称列表
        try:
            selected_categories = json.loads(user_filter.categories_selected)
        except json.JSONDecodeError:
            # 处理非法JSON的异常场景,默认返回空列表或全部分类
            selected_categories = []
        
        # 直接用分类名称列表查询Poller即可,不需要先查Category,减少一次数据库查询
        qs_poller = Poller.objects.filter(
            poller_category__category__in=selected_categories
        ).order_by('-created_on')[:100]
    else:
        # 原有未登录逻辑
        [...]

优化建议

当前用CharField存序列化JSON的方案兼容性和易用性都较差,可以直接改用Django原生的JSONField存储分类选择,无需手动做序列化/反序列化:

# 修改UserCategoryFilter模型字段
class UserCategoryFilter(models.Model):
    user = models.ForeignKey(Account, on_delete=models.CASCADE)
    # 替换原有CharField,默认值设为空列表
    categories_selected = models.JSONField(default=list)

修改后保存分类的逻辑也可以简化,不需要调用json.dumps:

if filter_form.is_valid():
    selection = filter_form.clean()
    # 直接存列表即可,不需要序列化
    selected_list = [c.category for c in selection['choices']]
    UserCategoryFilter.objects.update_or_create(
        user=request.user,
        defaults={"categories_selected": selected_list}
    )

查询时也可以直接取字段值使用,不需要json.loads处理。

内容的提问来源于stack exchange,提问作者JSRB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 01:09:03