0

I am trying to accomplish the following with Django REST framework. I have model Records, which has field. It has foreign key to User. Each user can create multiple records with different numbers, but cannot create more than one record with the same number for themselves. However, each other user can create a record for itself with same number. E.g. Users Joe and Jill. Joe can create a record with number 123 only once, if he tries to make another record with 123, he should not be allowed. However Jill can create 123 once for herself, but not allowed more again.

My guess is to create a validator inside the serializer, which is

class RecordSerializer(serializers.HyperlinkedModelSerializer): '''Serializer for Record''' class Meta: model = Record fields = [ 'user', 'number', 'otherfield', ] validators = [ UniqueValidator( queryset= Record.objects.filter(user=<current user>), ) ] 

However, I cannot get the current user inside validator property, or how can I accomplish this otherwise?

2 Answers 2

1

You should add the constraint both in the serializer level and model level just in case a record is created outside the serializer. So let's say the record has id and owner fields, add the unique_together property in the model's Meta class:

class Meta: unique_together = (('id', 'owner')) 

Then in the serializer, you can use the CurrentUserDefault advanced field to capture the logged-in user.

from rest_framework.validators import UniqueTogetherValidator class RecordSerializer(serializer.ModelSerializer): owner = serializers.HiddenField( default=serializers.CurrentUserDefault() ) class Meta: validators = [ UniqueTogetherValidator( queryset=Record.objects.all(), fields=['id', 'owner'] ) ] 

Of course, the serializer should be used in a view which requires authentication

Sign up to request clarification or add additional context in comments.

4 Comments

Guys! @Andee and @Ken4Sholars! thanks so much! I have spent a whole day finding a solution!
This answer at stackoverflow.com/a/55786819/7027427 points that UniqueConstraints should be preferred over unique_together, and that can be deprecated. Also I am getting <django.db.utils.IntegrityError: UNIQUE constraint failed:> error pointing to those fields, when migrating.
Yes, that is just the preferred way of specifying the unique constraints in the new versions of Django, so if you have such a version, please go ahead and use that instead of unique_together. As for the IntegrityError, it seems you are violating the unique constraint. That's exactly how it notifies the developer that it is being violated. I suspect that you are creating the record outside the serializer. Means that user already has a record with that number. Also, you may want to rename the id field in my answer to the number field you described in the question
I had records violating the constraint in the db. removed them and fixed :) thanks a lot once again.
1

On your model Meta, set unique_together https://docs.djangoproject.com/en/3.0/ref/models/options/#unique-together

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.