Django 1.11查询异常:多项目时点击编辑报错求助
嘿,这个报错我太熟了!MultipleObjectsReturned说白了就是你用get()查询的时候,数据库返回了不止一条结果,但get()方法天生就要求只能拿到唯一的一条数据。单个项目时正常,多个项目就炸,明显是你的编辑视图里的查询逻辑没精准定位到用户点击的那个项目。
咱们一步步来排查解决:
1. 先检查编辑视图的查询逻辑
十有八九是你在获取待编辑项目时,只过滤了当前登录用户,没加上项目的唯一标识(比如ID)。举个错误的例子,你可能写了类似这样的代码:
# 错误写法:只按用户筛选,多个项目时肯定返回多条 project = Project.objects.get(user=request.user)
正确的姿势是,必须同时用项目ID和当前用户作为查询条件,这样才能精准定位到用户点击的那个项目:
# 正确写法:结合项目ID和用户权限过滤 def edit_project(request, project_id): try: # 既确保是当前用户的项目,又确保是指定ID的那一个 project = Project.objects.get(id=project_id, user=request.user) except Project.DoesNotExist: # 处理项目不存在或者用户无权访问的情况 return HttpResponseNotFound("该项目不存在,或者你没有编辑权限哦") # 接下来就是编辑表单渲染、保存逻辑...
2. 确认URL和模板链接是否正确传递了项目ID
然后要检查你的URL路由有没有正确捕获项目ID参数,还有模板里的编辑链接有没有把项目ID传过去。比如模板里的链接应该是这样的:
<!-- 模板中项目名称的编辑链接:把project.id传给URL --> <a href="{% url 'edit_project' project.id %}">{{ project.name }}</a>
对应的urls.py里的配置得是这样:
# urls.py中的路由配置 urlpatterns = [ # 其他路由... url(r'^edit/(?P<project_id>\d+)/$', views.edit_project, name='edit_project'), ]
要是URL没捕获project_id,或者视图函数没接收这个参数,那查询时自然找不到具体的项目,只能拿到该用户的所有项目,触发报错。
3. 正确区分get()和filter()的使用场景
这里要提醒下:get()只用于你确定结果唯一的场景,如果你不确定结果数量,要么用filter().first(),要么就用try-except把MultipleObjectsReturned和DoesNotExist都捕获到。不过在编辑项目这个场景下,咱们就是要精准定位到单个项目,所以优先用带双条件的get(),再配合异常处理,既安全又符合业务逻辑。
4. 最后检查数据库数据(概率低但也不能忽略)
万一前面都没问题,那可以去数据库里看看,是不是同一个用户下有多个ID相同的项目?虽然主键ID是唯一的,这种情况很少见,但如果是手动修改过数据库数据,也有可能出现。要是真有重复数据,先清理掉就行。
按照上面的步骤走,应该就能解决这个问题了。核心就是确保编辑视图能精准定位到用户点击的那一个项目,而不是返回该用户的所有项目~
内容的提问来源于stack exchange,提问作者javaNewbie

