Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Suppress "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 serializer.is_valid() 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
        serializer.save()

Error:

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

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

like image 914
The Godfather Avatar asked Mar 25 '15 05:03

The Godfather


People also ask

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.

What is renderers in Django REST framework?

The rendering process takes the intermediate representation of template and context, and turns it into the final byte stream that can be served to the client. REST framework includes a number of built in Renderer classes, that allow you to return responses with various media types.

What is Django REST framework browsable API?

The browsable API feature in the Django REST framework generates HTML output for different resources. It facilitates interaction with RESTful web service through any web browser. To enable this feature, we should specify text/html for the Content-Type key in the request header.


1 Answers

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.

like image 171
Fiver Avatar answered Oct 21 '22 11:10

Fiver