发送序列化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
相关产品推荐
相关产品推荐

