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

如何通过单HTML表单存储Django一对多模型数据并避免医生记录重复

解决Django一对多模型重复创建关联对象的问题

核心问题分析

当前视图每次提交表单都会直接调用Doctor.objects.create()创建新医生记录,完全不检查数据库中是否已存在相同医生,这是重复创建的根本原因。此外还存在文件上传处理错误、性别选项不匹配的问题。

解决方案步骤

1. 用get_or_create避免重复创建医生

Django的get_or_create()方法会先尝试根据指定条件查询对象,不存在则创建,完美解决重复问题。选择手机号作为唯一标识条件(手机号具备唯一性,比姓名更可靠)。

2. 修复文件上传的处理逻辑

文件字段不能通过request.POST.get()获取,必须使用request.FILES.get(),你的表单已设置enctype="multipart/form-data",这部分无需额外修改。

3. 统一性别选项的取值

表单中性别选项值与模型定义的选项不匹配,需要统一两者取值,否则会触发模型验证失败。

4. 数据类型转换

表单提交的年龄、手机号等数值为字符串类型,需转换为整数后再存入模型的IntegerField字段。

修改后的代码

视图代码(views.py)

def requestlanding(request):
    if request.method == "POST":
        # 处理患者数据
        p_name = request.POST.get("patientName")
        p_age = int(request.POST.get("age"))
        p_gender = request.POST.get("gender").capitalize()
        p_phone = int(request.POST.get("contactPatient"))
        p_email = request.POST.get("emailPatient")
        p_wrecommend = request.FILES.get("wrecommend")

        # 处理医生数据
        d_name = request.POST.get("doctorName")
        d_phone = int(request.POST.get("contactDoctor"))
        d_specialization = request.POST.get("specialization")

        # 使用get_or_create避免重复创建医生,以手机号为唯一标识
        doctor, created = Doctor.objects.get_or_create(
            phone=d_phone,
            defaults={
                'name': d_name,
                'specialization': d_specialization
            }
        )
        # 若需更新已存在医生的信息,可在此添加额外逻辑

        # 创建患者并关联到医生
        patient = Patient.objects.create(
            doctor=doctor,
            name=p_name,
            email=p_email,
            phone=p_phone,
            age=p_age,
            gender=p_gender,
            wrecommend=p_wrecommend,
        )

        return redirect("requestlanding")
    return render(request, "docpatient.html")

表单代码(docpatient.html)

修改性别选项的value,与模型定义保持一致:

<select id="gender" name="gender" required>
    <option value="Male">Male</option>
    <option value="Female">Female</option>
    <option value="Others">Other</option>
</select>

模型代码(models.py)

可选:给Doctor的phone字段添加unique=True约束,从数据库层面避免重复手机号的医生:

phone = models.IntegerField(
    validators=[MinValueValidator(1000000000), MaxValueValidator(9999999999)],
    blank=False,
    unique=True
)

实现医生关联所有患者的功能

通过反向查询可获取医生的所有患者:

  • 默认反向关联名称为模型名小写加_set,在视图/模板中可使用doctor.patient_set.all()
  • 若要自定义反向关联名称,可在Patient模型的ForeignKey中添加related_name参数:
doctor = models.ForeignKey(Doctor, on_delete=models.PROTECT, related_name='patients')

之后即可用doctor.patients.all()获取该医生的所有患者。

内容的提问来源于stack exchange,提问作者Nabin Prasad Dhungana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 03:05:56