创建UserInfo对象时出现“matching query does not exist”错误排查
Google登录API创建UserInfo时触发UserInfo.DoesNotExist异常的原因及解决
问题代码
class GoogleSignIn(APIView): def post(self, request): settings = request.settings code = request.data['code'] # 验证Google OAuth授权码 try: google_user_info = verify_user(code) except Exception as e: print(str(e)) return Response({'error': 'Failed to verify with Google.'}) email = google_user_info['email'] picture = google_user_info['picture'] try: user = User.objects.get(email=email) user_info = UserInfo.objects.get(user=user) except User.DoesNotExist: first_name = google_user_info['given_name'] user = User.objects.create_user( email = email, username = email, first_name = first_name, last_name = google_user_info['family_name'], password=None) user_info = UserInfo.objects.create( user = user, credits = request.settings.INITIAL_CREDITS, expiry = compute_credits_expiry( num_days=settings.FREE_CREDITS_EXPIRY_IN_DAYS))
异常信息
Internal Server Error: /accounts/google-sign-in/ Traceback (most recent call last): File "/mnt/c/Dropbox/Parnasa/Web/wherewasit/backend/accounts/views.py", line 129, in post user = User.objects.get(email=email) File "/usr/lib/python3/dist-packages/django/db/models/manager.py", line 85, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 435, in get raise self.model.DoesNotExist( django.contrib.auth.models.User.DoesNotExist: User matching query does not exist. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/lib/python3/dist-packages/django/core/handlers/exception.py", line 47, in inner response = get_response(request) File "/usr/lib/python3/dist-packages/django/core/handlers/base.py", line 181, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/usr/lib/python3/dist-packages/django/views/decorators/csrf.py", line 54, in wrapped_view return view_func(*args, **kwargs) File "/usr/lib/python3/dist-packages/django/views/generic/base.py", line 70, in view return self.dispatch(request, *args, **kwargs) File "/home/meir/.local/lib/python3.10/site-packages/rest_framework/views.py", line 509, in dispatch response = self.handle_exception(exc) File "/home/meir/.local/lib/python3.10/site-packages/rest_framework/views.py", line 469, in handle_exception self.raise_uncaught_exception(exc) File "/home/meir/.local/lib/python3.10/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception raise exc File "/home/meir/.local/lib/python3.10/site-packages/rest_framework/views.py", line 506, in dispatch response = handler(request, *args, **kwargs) File "/mnt/c/Dropbox/Parnasa/Web/wherewasit/backend/accounts/views.py", line 140, in post user_info = UserInfo.objects.create( File "/usr/lib/python3/dist-packages/django/db/models/manager.py", line 85, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 453, in create obj.save(force_insert=True, using=self.db) File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 739, in save self.save_base(using=using, force_insert=force_insert, File "/usr/lib/python3/dist-packages/django/db/models/base.py", line 763, in save_base pre_save.send( File "/usr/lib/python3/dist-packages/django/dispatch/dispatcher.py", line 180, in send return [ File "/usr/lib/python3/dist-packages/django/dispatch/dispatcher.py", line 181, in <listcomp> (receiver, receiver(signal=self, sender=sender, **named)) File "/mnt/c/Dropbox/Parnasa/Web/wherewasit/backend/accounts/views.py", line 220, in your_model_pre_save old = UserInfo.objects.get(id=instance.id) File "/usr/lib/python3/dist-packages/django/db/models/manager.py", line 85, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 435, in get raise self.model.DoesNotExist( accounts.models.UserInfo.DoesNotExist: UserInfo matching query does not exist.
原因分析
从异常栈可以明确,问题并非出在UserInfo.objects.create()本身,而是绑定在UserInfo模型上的pre_save信号接收器your_model_pre_save。
执行UserInfo.objects.create()时,Django会先触发pre_save信号,此时新的UserInfo对象还未写入数据库,instance.id(主键)尚未生成。但信号处理函数里直接执行了old = UserInfo.objects.get(id=instance.id),尝试通过一个不存在的ID查询旧对象,必然会抛出UserInfo.DoesNotExist异常。
解决方法
修改your_model_pre_save信号处理函数,先判断当前对象是否为新建状态(即主键为空,还未保存到数据库),如果是则跳过查询旧对象的逻辑:
def your_model_pre_save(sender, instance, **kwargs): # 仅当对象已存在(主键不为空)时,才执行旧对象查询及后续逻辑 if instance.pk is not None: old = UserInfo.objects.get(id=instance.id) # 原有的后续处理代码...
这样在创建新UserInfo时,就不会执行无效的查询操作,避免抛出异常。
内容的提问来源于stack exchange,提问作者AlwaysLearning
相关产品推荐
相关产品推荐

