Django开发中检查外键关联记录是否已创建的实现问题
问题修复方案
核心问题梳理
你当前的代码存在几个逻辑错误,导致无法正确实现新增/更新关联记录的需求:
- 检查记录存在时直接判断QuerySet对象,性能较差,推荐使用Django内置的
exists()方法 - 表单的
instance参数传值错误:你给Fundamentals对应的表单传入了Project类型的实例,类型完全不匹配,会直接报错 Project查询使用filter后取下标[0],没有处理项目不存在的异常,也不够简洁- 外键字段赋值错误:你的
Fundamentals模型里的外键字段名为project_name,不是project,赋值时字段名对应不上 - 外键关联字段设置与查询逻辑不匹配:你给Fundamentals的外键指定了
to_field='project_name'(关联Project的project_name字段),但查询时传入的是Project的主键id,会导致查询结果不准确。如果不需要指定关联非主关键字段,建议删掉to_field='project_name'参数,使用默认的主键关联逻辑即可。
修正后的实现代码
from django.shortcuts import get_object_or_404, redirect, render from django.contrib.auth.decorators import login_required @login_required def Add_or_updateFundamentals(request, project_id): # 直接获取对应的Project实例,不存在直接返回404,更稳妥 project = get_object_or_404(Project, pk=project_id) # 用exists()检查关联的Fundamentals是否存在,性能更高 # 如果保留to_field='project_name'的设置,这里要改成filter(project_name_id=project.project_name) fund_exist = Fundamentals.objects.filter(project_name_id=project_id).exists() fund_instance = None if fund_exist: # 如果存在,拿到Fundamentals的实例,给表单用,这里才是正确的instance类型 # 如果保留to_field='project_name'的设置,这里要改成get(project_name_id=project.project_name) fund_instance = Fundamentals.objects.get(project_name_id=project_id) if request.method == 'POST': form = AddFundamentalsForm(request.POST, instance=fund_instance) if form.is_valid(): # 新增的时候给外键字段赋值,注意字段名是project_name,不是project if not fund_exist: form.instance.project_name = project form.save() return redirect('dashboard.html') else: form = AddFundamentalsForm(instance=fund_instance) if fund_exist: return render(request, 'pages/update_fundamentals.html', {'project': project, "form": form}) else: return render(request, 'pages/add_fundamentals.html', {'project': project, "form": form})
额外优化建议
- 如果你默认一个Project只能对应一个Fundamentals记录,建议把外键改成
OneToOneField,更符合业务逻辑,查询也更方便,直接用project.fundamentals就能拿到关联记录,不需要额外filter Fundamentals模型的__str__方法建议返回和自身相关的字段,而不是关联的Project名称,方便调试
内容的提问来源于stack exchange,提问作者JacksWastedLife
相关产品推荐
相关产品推荐

