13👍
Unfortunately, Andreas’s answer is not quite complete, as it will not work in the case of an update.
Instead, you would want something more like:
def validate(self, attrs):
field1 = attrs.get('field1', self.object.field1)
field2 = attrs.get('field2', self.object.field2)
try:
obj = Model.objects.get(field1=field1, field2=field2)
except StateWithholdingForm.DoesNotExist:
return attrs
if self.object and obj.id == self.object.id:
return attrs
else:
raise serializers.ValidationError('field1 with field2 already exists')
This will work for PUT, PATCH, and POST.
29👍
The ModelSerializer class has this functionality build-in, at least in djangorestframework>=3.0.0
, however if you are using a serializer
which doesn’t include all of the fields which are affected by your unique_together
constrain, then you’ll get an IntegrityError
when saving an instance which violates it. For example, using the following model:
class Foo(models.Model):
class Meta:
unique_together = ('foo_a', 'foo_b')
a = models.TextField(blank=True)
b = models.TextField(blank=True)
foo_a = models.IntegerField()
foo_b = models.IntegerField(default=2)
and the following serializer and ViewSet:
class FooSerializer(serializers.ModelSerializer):
class Meta:
model = models.Foo
fields = ('a', 'b', 'foo_a')
class FooViewSet(viewsets.ModelViewSet):
queryset = models.Foo.objects.all()
serializer_class = FooSerializer
routes = routers.DefaultRouter()
routes.register(r'foo', FooViewSet)
if you try to save two instances with the same foo_a
and foo_b
set, you’ll get an IntegrityError
. However, if we modify the serializer like this:
class FooSerializer(serializers.ModelSerializer):
class Meta:
model = models.Foo
fields = ('a', 'b', 'foo_a', 'foo_b')
you’ll then get a proper HTTP 400 BAD REQUEST
status code, and the corresponding JSON descriptive message in the response body:
HTTP 400 BAD REQUEST
Content-Type: application/json
Vary: Accept
Allow: GET, POST, HEAD, OPTIONS
{
"non_field_errors": [
"The fields foo_a, foo_b must make a unique set."
]
}
I hope this to result helpful for you, even when this is a somewhat old-posted question 😉
- [Django]-How to compare two JSON objects with the same elements in a different order equal?
- [Django]-Display django-pandas dataframe in a django template
- [Django]-DEBUG = True Django
25👍
I Needed this to override default message. Solved it by this.
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers, validators
class SomeSerializer(serializers.ModelSerializer):
"""
Demostrating How to Override DRF UniqueTogetherValidator Message
"""
class Meta:
model = Some
validators = [
validators.UniqueTogetherValidator(
queryset=model.objects.all(),
fields=('field1', 'field2'),
message=_("Some custom message.")
)
]
Similarly, you can specify fields.
- [Django]-In a django web application, how do you give users their own subdomain?
- [Django]-Django internationalization language codes
- [Django]-How to unit test file upload in django
4👍
Yes, you can do it in the .validate()
method of the serializer.
def validate(self, attrs):
try:
Model.objects.get(field1=attrs['field1'], field2=attrs['field2'])
except Model.DoesNotExist:
pass
else:
raise serializers.ValidationError('field1 with field2 already exists')
return attrs
The unique constraint that you set in your model is for creating database constraints, not for validating.
- [Django]-Django and VirtualEnv Development/Deployment Best Practices
- [Django]-Is it OK to use multiple inheritance with Django abstract models?
- [Django]-How to merge consecutive database migrations in django 1.9+?
2👍
Had the same problem and from this answer https://stackoverflow.com/a/26027788/6473175 I was able to get it to work but had to use self.instance
instead of self.object
.
def validate(self, data):
field1 = data.get('field1',None)
field2 = data.get('field2',None)
try:
obj = self.Meta.model.objects.get(field1=field1, field2=field2)
except self.Meta.model.DoesNotExist:
return data
if self.instance and obj.id == self.instance.id:
return data
else:
raise serializers.ValidationError('custom error message')
- [Django]-Docker – Can't access Django server
- [Django]-Deploying Django on Google App Engine ==> ERROR: (gcloud.app.deploy) NOT_FOUND: Unable to retrieve P4SA(…)
- [Django]-Updating User model in Django with class based UpdateView
-1👍
Well this is kinda stupid and it’s very unlikely that anyone but me would make this mistake, but I had put the same model in two serializers class, as a consequence I had this problem
Hope my mistake help someone!
- [Django]-Django: does the ORM support the SQL "IN" operator?
- [Django]-Django test runner not finding tests
- [Django]-Django development server, how to stop it when it run in background?