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

Django调用User.get()报MultipleObjectsReturned返回2条数据错误

报错根因

Django ORM的get()方法设计为仅返回1条匹配的查询结果:匹配0条抛出DoesNotExist异常,匹配≥2条就会抛出你遇到的MultipleObjectsReturned异常。
你的代码触发报错的直接原因及关联问题:

  • 两处User.objects.get()调用完全没有传入任何过滤参数,等价于查询User全表数据,只要表中用户数≥2必然触发异常,分别出现在message和getMessages两个视图函数中。
  • message视图中return render(...)写在用户判断、创建逻辑之前,return之后的代码永远不会执行,属于死代码。
  • User模型的username字段没有加唯一约束,允许重复用户名存入,即使加了过滤条件也可能匹配到多条记录。
  • Message模型的user字段用长字符串存储,没有和User做外键关联,getMessages视图中Message.objects.filter()也没有加过滤条件,会返回全量用户的所有消息,不符合业务预期。
  • 字段存在拼写错误:confrom_password应为confirm_password,后续表单校验容易出问题。
  • 存在冗余操作:objects.create()方法已经完成数据库写入,不需要再手动调用实例的save()方法。
修复步骤

1. 修正模型定义

如果是测试环境,建议先清空已有迁移文件和测试数据库,再替换为以下模型代码,避免字段变更导致的迁移冲突:

from django.db import models
from datetime import datetime

class User(models.Model):
    member_id = models.BigAutoField(primary_key=True)
    username = models.CharField(max_length=100, unique=True) # 加唯一约束,从库层面保证用户名不重复
    name = models.CharField(max_length=100)
    email = models.EmailField(max_length=50)
    password = models.CharField(max_length=100)
    confirm_password = models.CharField(max_length=50) # 修正拼写错误

class Message(models.Model):
    value = models.CharField(max_length=10000) # 去掉不合理的超长大数设置
    date = models.DateTimeField(default=datetime.now, blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE) # 改为外键关联User,级联删除

修改完成后依次执行python manage.py makemigrations和python manage.py migrate完成表结构更新。

2. 修正视图逻辑

调整代码执行顺序,给所有get()、filter()调用补全正确的查询条件,删除死代码和冗余操作:

from django.shortcuts import render, redirect
from django.http import HttpResponse, JsonResponse
from .models import User, Message

def message(request):
    username = request.GET.get('username')
    # 用get_or_create简化查询创建逻辑:存在则取出,不存在则新建
    user, _ = User.objects.get_or_create(username=username)
    # 响应逻辑放到所有业务逻辑最后,保证代码可执行
    return render(request, 'member/message.html', {
        'username': username,
        'user': user
    })

def send(request):
    # 加请求方法校验,避免GET请求直接访问报错
    if request.method == 'POST':
        message_content = request.POST['message']
        username = request.POST['username']
        # 用唯一字段username查询对应用户,不会返回多条结果
        send_user = User.objects.get(username=username)
        Message.objects.create(value=message_content, user=send_user)
        return HttpResponse('Message sent successfully')

def getMessages(request, user):
    # 从路径参数取用户名,查询唯一对应用户
    current_user = User.objects.get(username=user)
    # 仅过滤当前用户的消息,不返回全量数据
    user_messages = Message.objects.filter(user=current_user)
    return JsonResponse({"messages": list(user_messages.values())})
额外说明

所有用get()查询的场景,必须用带唯一约束的字段(比如主键、加了unique的username)作为查询条件,才能保证只返回1条结果,从根源避免MultipleObjectsReturned异常。视图函数中return语句之后的代码永远不会执行,写业务逻辑时要注意执行顺序。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 03:49:12