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

Django员工姓名+姓氏唯一校验失效问题排查请求

问题排查与修复方案

现有代码的核心问题

你的JrtnPerson模型里的save方法存在多处错误,直接导致组合唯一约束不生效:

  1. 类访问语法错误:self.JrtnPerson.objects写法错误,实例不能通过自身访问类名作为属性,正确写法应为JrtnPerson.objects或self.__class__.objects。
  2. super调用参数错误:super(surname,name,self).save(...)完全不符合语法,super()的参数应为当前类和实例,正确写法是super(JrtnPerson, self).save(*args, **kwargs)(Python2)或直接super().save(*args, **kwargs)(Python3)。
  3. 无错误提示逻辑:当前代码仅跳过重复数据的保存,但未抛出任何错误提示,用户无法感知操作失败原因。
  4. 未处理更新场景:编辑现有记录时,会把自身判定为重复数据,导致正常更新操作无法执行。
  5. 并发风险:仅通过save方法做检查,高并发场景下可能出现多个请求同时通过校验,最终插入重复数据。

正确实现方式

推荐结合数据库层面约束和模型验证逻辑实现,既保证数据一致性,又能给出友好的错误提示:

1. 修复模型类

from django.db import models
from django.core.exceptions import ValidationError

class JrtnPerson(models.Model):
    rtn = models.ForeignKey(Drtn, verbose_name='Подразделение Ростехнадзора', on_delete=models.CASCADE)
    name = models.CharField(max_length=200, verbose_name='Имя и Отчество')
    surname = models.CharField(max_length=200, verbose_name='Фамилия')
    tel_mob = PhoneNumberField(verbose_name="Номер телефона мобильный", blank=True, null=True)
    tel_rab = PhoneNumberField(verbose_name="Номер телефона рабочий", blank=True, null=True)
    email = models.EmailField(max_length=100, verbose_name="Электронная почта", blank=True, null=True)

    class Meta:
        # 添加数据库级唯一约束,从根源防止重复
        constraints = [
            models.UniqueConstraint(fields=['name', 'surname'], name='unique_full_name')
        ]

    def clean(self):
        # 模型层提前验证,给出友好提示
        existing = JrtnPerson.objects.filter(name=self.name, surname=self.surname)
        # 编辑时排除自身,避免误判
        if self.pk:
            existing = existing.exclude(pk=self.pk)
        if existing.exists():
            raise ValidationError('该姓名组合已存在,请检查输入')

    def save(self, *args, **kwargs):
        # 先触发验证逻辑
        self.clean()
        super().save(*args, **kwargs)

2. 修复Admin类

ModelAdmin不需要嵌套Meta类,直接指定model属性即可:

class JrtnPersonPersonAdmin(admin.ModelAdmin):
    list_display = ('name', 'surname', 'rtn',)
    search_fields = ('rtn__name_short', 'rtn__name_full', 'name', 'surname', 'tel_mob', 'tel_rab', 'email')
    model = JrtnPerson  # 直接关联模型,无需Meta类

3. Inline类说明

JrtnCuratorInline本身与唯一性约束无关,若JrtnCurator关联JrtnPerson,当在Inline中选择重复人员时,数据库约束会自动触发错误,Django Admin会捕获并显示提示,无需额外修改。

方案优势

  • 数据库约束:即使绕过模型层直接操作数据库,也能保证数据唯一性,避免脏数据。
  • 提前验证:在保存前触发clean方法,给用户友好的错误提示,替代生硬的数据库报错。
  • 兼容更新:排除自身实例,确保编辑现有记录时不会误判为重复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:46:19