Django REST Framework中get_or_create无法设置authUserId属性的问题
问题分析与修复方案
你的SpenderSerializer.create方法存在几个关键问题,导致authUserId始终为空:
1. 错误的用户ID获取方式
Django的User模型实例是对象而非字典,不能用user.get('id')来获取ID,这会直接抛出AttributeError,导致代码进入except分支,authUserId保持为None。
正确写法应该直接访问实例属性:
authUserId = user.id # 或者 user.pk
2. 邮箱匹配问题(隐性)
你POST的请求数据中邮箱是johndoew@gmail.com,但数据库中User表的对应邮箱是djohndoew@gmail.com(开头多了一个d),这会导致User.objects.get(email=...)抛出User.DoesNotExist异常,同样进入except分支。需要确保请求的邮箱与数据库中的完全一致(注意大小写,Django默认邮箱查询是区分大小写的,除非你修改了字段的db_collation)。
3. get_or_create参数逻辑问题
在你尝试的第二种写法中,将authUserId=authUserId和**validated_data一起作为查询条件传递给get_or_create,这会导致:如果存在邮箱匹配但authUserId为空的Spender记录,会直接返回该记录而不会更新authUserId。正确的做法是把authUserId放在defaults里,仅用邮箱等核心字段作为查询条件。
修复后的完整create方法
def create(self, validated_data): authUserId = None request_email = validated_data.get("email") try: # 若需要不区分大小写匹配邮箱,可改为 email__iexact=request_email user = User.objects.get(email=request_email) authUserId = user.id except User.DoesNotExist: # 明确捕获指定异常,避免捕获所有异常导致的隐藏问题 pass # 用邮箱作为查询条件,其他字段(含authUserId)放入defaults return Spender.objects.get_or_create( email=validated_data["email"], defaults={ **validated_data, 'authUserId': authUserId } )[0]
额外的优化点
validate方法中self.instance.name是错误的,你的Spender模型没有name字段,应改为self.instance.email。- 避免使用裸
except:,明确捕获User.DoesNotExist和MultipleObjectsReturned异常,防止隐藏其他错误。 - 视图中的
queryset多了一个逗号,导致它变成元组,正确写法是queryset = Spender.objects.all()。
内容的提问来源于stack exchange,提问作者AlexTank
相关产品推荐
相关产品推荐

