Jessie Liauw A Fong
Jessie Liauw A Fong

Reputation: 200

Django rest framework unique together error message not displayed anymore

I worked with django rest framework a lot and everything worked fine until today. The same function suddenly returns something different. I have a unique together on my client model with name and company. I recently created a mixin called AutoCompany which automatically sets the company on the client.

My client model:

class Client(AutoCompany):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=155)
    description = models.TextField(blank=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=["name", "company"], name="Name and company"),
        ]

AutoCompany


class AutoCompany(models.Model):
    company = models.ForeignKey("company.Company", models.DO_NOTHING)

    def save(self, *args, **kwargs):
        company = apps.get_model("company.Company")

        try:
            self.company
        except company.DoesNotExist:
            self.company = get_request().user.company

        self.after_company_set()

        return super().save(*args, **kwargs)

    def after_company_set(self):
        pass

    class Meta:
        abstract = True

So previously when I created a client with the same name for the same company I got a 400 response with this error:

The fields name, company must make a unique set.

My serializer looks like this:

class ClientSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Client
        fields = ["id", "name", "description"]

But now I just get a 500 response with a python error. It seems like the error is not caught anymore. Now I just get:

django.db.utils.IntegrityError: (1062, "Duplicate entry 'test-cafd0ed10f9f4865a1d56abb67daa831' for key 'Name and company'")

Does anybody know why this change occurred?

Upvotes: 3

Views: 3965

Answers (1)

Tom Carrick
Tom Carrick

Reputation: 6616

DRF doesn't validate UniqueConstraints the way it does unique_together.

The reason for this is because unique constraints can be more complex than just "this collection of fields must have unique values". Consider the following:

UniqueConstraint(
    fields=["author", "slug"],
    condition=Q(status="published"),
    name="author_slug_published_uniq",
)

This constraint only validates that the row is unique if the status is published, i.e. there can be multiple rows with the same slug and author if they are all drafts. Because of this complexity, there isn't a validator for this. However, for this simple case, you can add DRF's UniqueTogether validator manually:

class ClientSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ["id", "name", "description", "company"]
        validators = [
            UniqueTogetherValidator(
                queryset=Client..objects.all(),
                fields=["name", "company"],
            )
        ]

Upvotes: 11

Related Questions