The Godfather The Godfather - 1 year ago 86
Python Question

Supress "field should be unique" error in Django REST framework

I have a model like

class MyModel(models.Model):
uuid = models.CharField(max_length=40, unique=True)

and a serializer

class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('uuid')

And I want to receive JSON with MyModel object but it can be existing objects. So, when I use
with data about existing object it gives me an error:

for record in request['records']:
# request - body of JSON request,
# 'records' - array of records I want to add or update

serializer = MyModelSerializer(data=record)
if serializer.is_valid():
# Do stuff


{"uuid":["This field must be unique."]}

Is there a way to separate behavior for new and existing objects? Particularly, I want to create new
object if it's not it database yet and update existing
object if it's present.

Answer Source

You are basically overloading a single entry point of your REST API by trying to both create new instances and update existing instances using a POST request. In addition, it seems you are trying to create and update multiple instances simultaneously within a single POST request.

Django REST Framework (DRF) expects a POST request to only create new instances. Therefore, sending an existing instance record triggers a unique constraint violation for the uuid field since DRF tries to create that record as a new instance, as the existing instance already has that uuid value.

A solution to make your REST API more "RESTful" would be to separate the creation and updating of records into POST and PUT requests respectively. It is unclear if you are using the generic API views provided by DRF, but you can use the CreateAPIView to POST new instances, then create a separate UpdateAPIView to PUT and/or PATCH existing instances. Even better you could allow retrieval via GET for both of these endpoints using the generic views ListCreateAPIView and RetrieveUpdateAPIView.

Finally, for handling bulk requests (i.e. multi-instances in a single request) you can either override the built-in view methods or use a 3rd-party package such as django-rest-framework-bulk.