pythondjangodjango-modelsslug

Django Raise Error When Slug Already Exist


I have a simple model like this:

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."})

I want to raise an error instead of creating a new slug whenever the slug already exist, but the error is not raised by the AutoSlugField

I tried another way by override the save method of my model like this:

def save(self, *args, **kwargs):
    self.slug = slugify(self.title)
    super(Competition, self).save(*args, **kwargs)

and validate it in my serializer like this:

class MyModelSerializer(serializers.ModelSerializer):
   class Meta:
      model = MyModel
      fields = '__all__'
    
  def validate_title(self, val):
      if MyModel.objects.filter(slug=slugify(val)).exists():
          raise serializers.ValidationError('The slug of title has been registered.')
      return val

This actually works fine while creating a new object but has a problem when updating the object, since if the slug remains the same it raises the error, but it should not because I am updating the same object.

What is the most convenient way to do this? I really appreciate any help. Thank you...


Solution

  • You should exclude the object you are updating, so:

    class MyModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = MyModel
            fields = '__all__'
    
        def validate_title(self, val):
            qs = MyModel.objects.filter(slug=slugify(val))
            if self.instance is not None:
                qs = qs.exclude(pk=self.instance.pk)
            if qs.exists():
                raise serializers.ValidationError(
                    'The slug of title has been registered.'
                )
            return val

    We thus check if there is an instance in the serializer to update, and if that is the case, we exclude from the queryset the object with the same primary key .pk.