When building my API that would list places (that offer products) and users can rate both places and products I needed a way to limit user to one review per place and one review per product.
I couldn't find any solution online so I came up with my own. If you know better way, please let me know down in the comments. Thanks!
This problem likely should be handled on database level (or rather ORM) level but I wanted to explore Django Rest Framework so I created validation in the serializer.
You can implement validate
method on your serializer to validate the data. With this I faced issues with not having all the available data available for validation. Turns out, you can provide additional context for your serializer inside view with get_serializer_context
.
I used this method to add product_id
and the request
itself to the context for use in validate
method like so:
def get_serializer_context(self):
return {'product_id': self.kwargs['product_id'], 'request': self.request}
With this ready, the validate
method can be implemented:
def validate(self, data):
product_id = self.context["product_id"]
if Review.objects.filter(product_id=product_id, author=self.context["request"].user).exists():
raise serializers.ValidationError("This user has already added review for this product")
return data
I first get product_id
from the context
and then check whether Review
object for this product exists by this user which I can get from request
. If it does, we can raise
ValidationError
and explain what is wrong.
Users can still add reviews but in case they decide to add another, the validate
method will prevent them from doing so.
This particular API is for mobile app which would do this validation on its part. AKA when user enters reviews section for product/place it would already load this user's review and display it for possible edit. So the above is more like additional check to prevent unwanted data in the database.
Thanks for reading! And do let me know if you have better solution.
Top comments (0)