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

Django Admin&Django2.0:如何禁止患者自身作为其责任人?

解决Django中患者不能设置自身为责任人的问题

嘿,作为Django 2.0的新手碰到这种关联逻辑的限制需求很正常,我给你几个实用的方案,都是在Django 2.0里能直接落地的:

方案1:模型层添加clean方法(最推荐)

模型层的验证是最底层的,不管你是通过admin后台、表单提交还是代码直接修改数据,都会触发这个验证,能从根源上保证数据的合法性。

假设你的模型结构是基于User多表继承的,修改Patient模型如下:

from django.db import models
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError

class Patient(User):
    # 你的自定义字段,比如病历号
    medical_record_no = models.CharField(max_length=20, unique=True)
    # 关联责任人:一个Patient对应一个Responsible,一个Responsible对应多个Patient
    responsible = models.ForeignKey('Responsible', on_delete=models.CASCADE, related_name='patients')

    def clean(self):
        # 先调用父类的clean方法,保留原有验证逻辑
        super().clean()
        # 检查当前患者和选中的责任人是否为同一用户
        # 多表继承下,User子类会有user_ptr字段关联到父类User
        if self.responsible.user_ptr == self.user_ptr:
            raise ValidationError("患者不能将自身设置为责任人")

class Responsible(User):
    # 你的自定义字段,比如联系电话
    contact_phone = models.CharField(max_length=11)

当你尝试保存不符合规则的Patient实例时,Django会抛出ValidationError,不管是在admin操作还是代码里创建对象,都会拦截不合法的数据。

方案2:表单层添加字段验证

如果你主要通过表单来创建/编辑患者信息,可以在表单里针对responsible字段做验证:

from django import forms
from .models import Patient

class PatientForm(forms.ModelForm):
    class Meta:
        model = Patient
        fields = ['username', 'email', 'medical_record_no', 'responsible']

    def clean_responsible(self):
        selected_responsible = self.cleaned_data.get('responsible')
        # 分两种情况:创建新患者/编辑已有患者
        if self.instance.pk:
            # 编辑模式:直接对比当前患者和选中的责任人
            if self.instance.user_ptr == selected_responsible.user_ptr:
                raise forms.ValidationError("不能选择自己作为责任人")
        else:
            # 创建模式:对比表单提交的用户名和责任人的用户名
            if self.cleaned_data.get('username') == selected_responsible.username:
                raise forms.ValidationError("不能选择自己作为责任人")
        return selected_responsible

这种方法的缺点是:如果有人通过代码直接修改数据库(比如shell里操作),这个验证不会触发,所以只适合纯表单驱动的场景。

方案3:使用pre_save信号拦截

如果你不想修改模型或表单,可以用Django的信号机制在保存前拦截不合法数据:

from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.core.exceptions import ValidationError
from .models import Patient

@receiver(pre_save, sender=Patient)
def check_responsible_self(sender, instance, **kwargs):
    if instance.responsible.user_ptr == instance.user_ptr:
        raise ValidationError("患者不能设置自身为责任人")

信号会在模型实例保存前自动触发,同样能拦截不合法数据,但相比模型层的clean方法,它的逻辑分散在模型外,可读性稍差,优先级不如方案1。

小提示

如果你用Django Admin管理患者,模型的clean方法会自动被调用,当你在后台选择自己作为责任人时,页面会直接弹出错误提示,非常直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:56:42