Django中Slug已存在时如何抛出错误而非自动生成新Slug
解决方案
方法一:序列化器验证中排除当前实例
修改序列化器的validate_title方法,在查询重复slug时,自动排除当前正在更新的对象——因为更新操作时序列化器会有self.instance属性指向当前对象,创建时该属性为None,正好可以用来区分场景:
class MyModelSerializer(serializers.ModelSerializer): class Meta: model = MyModel fields = '__all__' def validate_title(self, val): target_slug = slugify(val) # 先筛选出slug匹配的记录 queryset = MyModel.objects.filter(slug=target_slug) # 如果是更新操作,排除当前实例 if self.instance is not None: queryset = queryset.exclude(pk=self.instance.pk) # 检查是否存在重复 if queryset.exists(): raise serializers.ValidationError('The slug of title has been registered.') return val
同时建议调整模型的AutoSlugField配置,关闭它的自动重命名功能,这样当slug重复时会直接触发唯一约束错误,而不是自动生成新slug:
slug = AutoSlugField( populate_from='title', unique=True, error_messages={'unique':"The slug of title has already been registered."}, always_update=False # 关闭自动更新,避免自动生成新slug )
方法二:模型层添加验证逻辑
如果希望无论通过序列化器还是后台管理操作都能触发验证,可以在模型的clean方法中实现逻辑,确保模型层面的约束:
from django.core.exceptions import ValidationError from django.utils.text import slugify class MyModel(models.Model): title = models.CharField(max_length=255) slug = AutoSlugField( populate_from='title', unique=True, error_messages={'unique':"The slug of title has already been registered."}, always_update=False ) def clean(self): super().clean() target_slug = slugify(self.title) queryset = MyModel.objects.filter(slug=target_slug) # 排除当前实例(更新场景) if self.pk is not None: queryset = queryset.exclude(pk=self.pk) if queryset.exists(): raise ValidationError({'slug': 'The slug of title has already been registered.'})
内容的提问来源于stack exchange,提问作者Dra-Code
相关产品推荐
相关产品推荐

