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

发送序列化User对象至后台任务后无法获取Profile,求解决方案

问题分析与解决方案

看起来你遇到的核心问题是序列化后的User对象只是JSON字符串,不是Django ORM实例,所以在后台任务里直接用它去查询Profile肯定找不到对应的记录。咱们一步步来解决:

问题根源

在query.py里,你把User对象序列化成JSON字符串发送到Channel Layer:

async_to_sync(channel_layer.send)('accounts', {
    'type': 'calculate.profile.percentage',
    'text': serializers.serialize('json', [info.context.user, ])
})

但在AccountBackgroundTasks的calculate_profile_percentage方法里,你直接从context里拿user(其实是这个JSON字符串),然后尝试用它作为查询条件:

user = context.get('user')
profile_instance = model_to_dict(Profile.objects.get(user=user))

这就好比拿一串文本去匹配数据库里的User对象,当然会找不到Profile了。

最优解决方案:发送用户ID而非序列化对象

传整个User对象既冗余又容易出问题,直接传用户ID是最简单高效的方式:

1. 修改query.py中的发送逻辑

把发送的内容改成用户ID:

@staticmethod
def resolve_profile(self, info, **kwargs):
    print('info', info.context.user) # type <class 'apps.accounts.models.User'>
    print('type', type(info.context.user))
    if info.context.user.is_authenticated:
        channel_layer = get_channel_layer()
        print("channel_layer", channel_layer)
        async_to_sync(channel_layer.send)('accounts', {
            'type': 'calculate.profile.percentage',
            'user_id': info.context.user.id  # 直接传用户ID
        })
        return Profile.objects.get(user=info.context.user)
    return None

2. 修改consumers.py中的接收逻辑

通过ID获取User实例,再查询Profile:

class AccountBackgroundTasks(SyncConsumer):
    def calculate_profile_percentage(self, context):
        print("arrived here successfully")
        logger.info("context: %s", context)  # 修复logger参数传递问题
        weight = {'full_name': 10, 'age': 10, 'city': 10, 'address': 10}
        total = 0
        try:
            user_id = context.get('user_id')
            # 通过ID获取真实的User ORM实例
            user = User.objects.get(id=user_id)
            profile_instance = model_to_dict(Profile.objects.get(user=user))
            for field in profile_instance:
                if field in weight:  # 用in判断避免KeyError,替代原错误的AttributeError捕获
                    total += weight[field]
        except Profile.DoesNotExist:
            logger.error("Profile does not exist for user ID: %s", user_id)
            return
        except User.DoesNotExist:
            logger.error("User does not exist with ID: %s", user_id)
            return
        return total

备选方案:反序列化JSON字符串(不推荐)

如果你一定要传序列化后的对象,需要先反序列化得到User实例,但这样做没必要,而且增加复杂度:

# 在consumers.py的calculate_profile_percentage方法里
import json
from django.core import serializers

def calculate_profile_percentage(self, context):
    # ... 其他代码
    try:
        user_data = json.loads(context.get('text'))
        # 反序列化得到User实例
        user = serializers.deserialize('json', user_data).next().object
        profile_instance = model_to_dict(Profile.objects.get(user=user))
        # ... 后续逻辑
    except Exception as e:
        logger.error("Error deserializing user: %s", str(e))
        return

额外小优化

  • 把except AttributeError改成except KeyError,因为你是在字典里找字段,不存在的话抛出的是KeyError
  • 日志输出要正确传递参数,比如logger.info("context: %s", context)而不是logger.info("context", context)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 06:32:11