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

Django如何将unique_together错误关联至指定字段?

问题描述

我在开发多租户应用,所有数据均关联至Tenant模型。创建模型时需要确保name字段的唯一性,但该唯一性仅需在租户内生效,而非全局生效,因此使用了unique_together(后续会迁移至UniqueConstraint)。

然而当唯一性约束被违反时,系统会添加non_field_error,我希望将该错误关联至name字段——因为tenant字段是隐式的,对用户不可见(始终为当前登录用户所属租户,不可选择)。

请问如何实现这一需求?优先考虑在模型层实现,其次可在表单层实现。我曾考虑先验证模型,再将错误从non_field_errors转移至name字段,但这种方式感觉不太合理。

初始代码:

class Company(models.Model):
    tenant = models.ForeignKey(Tenant, on_delete=models.PROTECT)
    name = models.CharField(max_length=255)

    class Meta:
        unique_together = ('tenant', 'name')

解决方案

方法一:模型层自定义验证(优先推荐)

直接在模型的clean方法中手动校验租户内的名称唯一性,错误会直接绑定到name字段:

from django.core.exceptions import ValidationError

class Company(models.Model):
    tenant = models.ForeignKey(Tenant, on_delete=models.PROTECT)
    name = models.CharField(max_length=255)

    class Meta:
        # 后续可替换为UniqueConstraint,逻辑一致
        unique_together = ('tenant', 'name')

    def clean(self):
        super().clean()
        # 校验当前租户下是否已存在同名记录,编辑时排除自身
        exists = Company.objects.filter(
            tenant=self.tenant,
            name=self.name
        ).exclude(pk=self.pk).exists()
        
        if exists:
            raise ValidationError({
                'name': '当前租户下已存在该名称'
            })

注意:调用model.save()时不会自动触发clean方法,需手动调用model.full_clean(),或者通过Django的ModelForm操作(表单会自动触发模型的clean)。

方法二:表单层转移错误

如果不想修改模型,可在ModelForm中捕获全局错误并转移到name字段:

from django import forms
from .models import Company

class CompanyForm(forms.ModelForm):
    class Meta:
        model = Company
        fields = ['name']  # 不暴露tenant字段

    def clean(self):
        cleaned_data = super().clean()
        
        # 识别唯一性相关的全局错误
        if self.non_field_errors():
            for error in self.non_field_errors():
                if "unique" in error.lower() or "已存在" in error:
                    self.add_error('name', error)
            # 移除原全局错误
            self._errors.pop('__all__', None)
        
        return cleaned_data

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 03:12:46