Reputation: 200
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
Reputation: 6616
DRF doesn't validate UniqueConstraint
s 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