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

Django模型UniqueConstraint仅在Admin生效,新增重复数据问题求助

问题

在Django模型中使用UniqueConstraint类时遇到异常:模型已配置联合唯一约束,但通过自定义表单的create()方法、手动MySQL插入都能添加重复数据,仅Django Admin后台添加时约束生效。相关代码如下:

模型代码

class ModeleEquipement(models.Model):
    id = models.AutoField(primary_key=True)
    fabricant = models.ForeignKey(FabricantEquipement, on_delete=models.SET_DEFAULT, default='')
    type = models.ForeignKey(TypeEquipement, on_delete=models.SET_DEFAULT, default='')
    reference = models.CharField(max_length=50, default='')
    designation = models.CharField(max_length=50, default='')
    
    def __str__(self):
        return str(self.id)
    
    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['fabricant', 'type', 'reference', 'designation'], name='unique_model_constraint')
        ]

后端数据创建代码

form = ModeleEquipementForm(request.POST)
if form.is_valid():
   fabricant = FabricantEquipement.objects.get(id=form.cleaned_data["fabricant"])
   type = TypeEquipement.objects.get(id=form.cleaned_data["type"])
   ModeleEquipement.objects.create(
       designation=form.cleaned_data["designation"],
       reference=form.cleaned_data["reference"],
       fabricant=fabricant,
       type=type
       )

表单代码

class ModeleEquipementForm(forms.Form):
    fabricant = forms.ChoiceField(widget=forms.Select())
    type = forms.ChoiceField(widget=forms.Select())
    reference = forms.CharField(label="Référence", max_length=20)
    designation = forms.CharField(label="Désignation", max_length=50)
    action = forms.CharField(widget=forms.HiddenInput(attrs={'value': 'add_modele'}))

解决方案

1. 同步数据库约束

Django的UniqueConstraint需要通过迁移操作同步到MySQL数据库才会生效。Admin后台生效是因为它在ORM层面做了前置校验,但直接create()或手动数据库插入时,只有数据库层面的约束能拦截重复数据。

执行以下命令完成约束同步:

python manage.py makemigrations
python manage.py migrate

之后可以登录MySQL,检查modeleequipement表是否存在unique_model_constraint这个联合唯一索引。

2. 改用ModelForm实现表单校验

当前使用的forms.Form是普通表单,不会自动继承模型的唯一性校验逻辑,form.is_valid()仅检查字段格式合规性。而Django Admin使用的是ModelForm,会自动关联模型的约束规则。

将表单修改为ModelForm:

class ModeleEquipementForm(forms.ModelForm):
    action = forms.CharField(widget=forms.HiddenInput(attrs={'value': 'add_modele'}))
    
    class Meta:
        model = ModeleEquipement
        fields = ['fabricant', 'type', 'reference', 'designation']

后端代码也可以简化为直接调用save():

form = ModeleEquipementForm(request.POST)
if form.is_valid():
    form.save()

3. 捕获数据库完整性异常

即使数据库约束生效,直接调用create()遇到重复数据时会抛出IntegrityError,需要在代码中捕获并处理,避免静默插入失败:

from django.db import IntegrityError

form = ModeleEquipementForm(request.POST)
if form.is_valid():
    try:
        fabricant = FabricantEquipement.objects.get(id=form.cleaned_data["fabricant"])
        type = TypeEquipement.objects.get(id=form.cleaned_data["type"])
        ModeleEquipement.objects.create(
            designation=form.cleaned_data["designation"],
            reference=form.cleaned_data["reference"],
            fabricant=fabricant,
            type=type
        )
    except IntegrityError:
        form.add_error(None, "该组合已存在,请检查输入")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:26:29