Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework: how to make field required / read-only only for update actions such as PUT and PATCH?

I have a Django Serializer that has a field that should only be required for update actions such as PUT and PATCH. But not for create actions such as POST.

I found this similar SO question but there's no clue there regarding how to write a custom validation to detect whether an action is for create or update or patch.

Similarly, I want to turn on read_only (or make them not editable) for some other fields but only for update actions.

I have googled the django rest framework docs, but there's no explicit examples of such custom validators.

Right now, my workaround is to set required=false altogether which is not the best.

Please advise.

like image 582
Kim Stacks Avatar asked Dec 12 '18 04:12

Kim Stacks


People also ask

What is write only field Django REST framework?

From DRF v3 onwards, setting a field as read-only or write-only can use serializer field core arguments mentioned as follows. write_only. Set this to True to ensure that the field may be used when updating or creating an instance, but is not included when serializing the representation.

What is difference between APIView and ViewSet?

APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.

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.

How do I update user details in Django REST framework?

Open auth/urls.py and add update profile endpoint. we should send a PUT request to API for checking update profile endpoint. We must add username, first_name, last_name and email. If fields passed validations, user profile will be changed.


2 Answers

What I do in such situations is have a different serializer altogether that inherits from a base serializer and overrides the relevant fields. So in you case, an approach like this should work:

class CreateSerializer(serializers.Serializers):
    field = serializers.CharField(max_length=100)

class UpdateSerializer(CreateSerializer):
    field = serializers.CharField(max_length=100, required=False)

And in your view, return the relevant serializer:

def get_serializer_class(self):
    if self.request.action == "POST":
        return CreateSerializer
    elif self.request.action in ["PUT", "PATCH"]:
        return UpdateSerializer

I think this is a good approach to take because you might need to add additional logic in the future based on the request method. It's also more readable than monkey patching the field's required attribute.

like image 178
Saad Aleem Avatar answered Sep 21 '22 15:09

Saad Aleem


You can override the get_fields methods of serializer and then you can change the value of that fields

class SomeDataSerializer(serializers.ModelSerializer):
    some_field = serializers.CharField(max_length=100)

    def get_fields(self, *args, **kwargs):
        fields = super(SomeDataSerializer, self).get_fields(*args, **kwargs)
        request = self.context.get('request', None)
        if request and getattr(request, 'method', None) == "POST":
            fields['some_field'].required = False
        return fields
like image 31
aman kumar Avatar answered Sep 20 '22 15:09

aman kumar