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

多商家添加同名食品分类触发唯一约束报错的技术咨询

解决不同商家无法添加同名食品分类的问题

问题原因

当前数据库中category_name字段被设置了全局唯一约束,导致所有商家的分类名不能重复,不符合业务需求——正确逻辑应为:同一商家下分类名唯一,不同商家允许使用同名分类。

解决方案

1. 修正模型的唯一约束

修改models.py中的Category模型,在Meta类中添加联合唯一约束,确保vendor和category_name的组合唯一:

class Category(models.Model):
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE)
    category_name = models.CharField(max_length=50)
    slug = models.SlugField(max_length=100, unique=True)
    description = models.TextField(max_length=250, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = 'category'
        verbose_name_plural = 'categories'
        # 添加联合唯一约束:同一商家下分类名不能重复
        constraints = [
            models.UniqueConstraint(fields=['vendor', 'category_name'], name='unique_vendor_category')
        ]

    def clean(self):
        self.category_name = self.category_name.capitalize()

    def __str__(self):
        return self.category_name

2. 更新数据库约束

执行以下命令生成并应用迁移,让数据库生效新的约束规则:

python manage.py makemigrations
python manage.py migrate

注意:若原有数据存在同一商家下的重复分类名,迁移会失败,需先手动清理重复数据。

3. 优化Slug生成逻辑(可选)

原Slug生成仅依赖分类名+ID,可结合商家信息让Slug更具语义性,同时保证唯一性:
修改views.py中的Slug生成代码:

# 替换原Slug生成逻辑
category.slug = slugify(f"{category.vendor.id}-{category_name}") + f'-{category.id}'
category.save()

4. 增强表单验证(可选)

在表单层面提前拦截同一商家下的重复分类名,修改forms.py:

class CategoryForm(forms.ModelForm):
    class Meta:
        model = Category
        fields = ['category_name', 'description']

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super().__init__(*args, **kwargs)

    def clean_category_name(self):
        category_name = self.cleaned_data.get('category_name').capitalize()
        # 获取当前提交表单的商家实例(根据你的用户-商家关联逻辑调整)
        vendor = self.request.user.vendor
        if Category.objects.filter(vendor=vendor, category_name=category_name).exists():
            raise forms.ValidationError("该分类名已存在,请更换")
        return category_name

同时在视图中传递request给表单:

# 替换视图中表单初始化代码
category_form = CategoryForm(request.POST, request=request)  # POST请求时
# GET请求时
category_form = CategoryForm(request=request)

5. 修复视图错误提示

原视图中表单验证失败时仅显示模糊提示,改为显示具体错误信息:

else: 
    # 遍历表单错误并逐一提示
    for field, errors in category_form.errors.items():
        for error in errors:
            messages.error(request, f"{category_form[field].label}: {error}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:50:22