简体   繁体   中英

How to access extra data sent with POST request in Django Rest Framework serializer

I'm trying to send an extra array with a POST request that creates a group.

POST /groups/
{
  "name": “New Group“,
  "users_to_invite": [ 1, 2, 6 ]
}

I'm using Django Rest Framework 's ListCreateAPIView to handle the request:

class GroupListView(ListCreateAPIView):
    queryset = Group.objects.all()

    def get_serializer(self, *args, **kwargs):
        kwargs['context'] = self.get_serializer_context()

        # Use a dedicated serializer to inspect the field with users to invite
        if self.request.method == 'POST':
            return GroupCreateSerializer(*args, **kwargs)
        return GroupSerializer(*args, **kwargs)

I want to get to the contents of the users_to_invite array in a serializer to create invitation objects. However, I'm unable to do so because somehow the array is not there when I'm accessing it in the serializer.

class GroupCreateSerializer(ModelSerializer):

    def create(self, validated_data):
        # Get user ids to invite
        # !! It fails here !!
        invitations_data = validated_data.pop('users_to_invite')

        # TODO: Iterate over ids and create invitations

        # Create a group
        group = Group.objects.create(**validated_data)
        return group

    class Meta:
        model = Group
        fields = ('id', 'name', )

Array is not there so naturally I'm getting the error:

File "...my_api/serializers.py", line 303, in create
    invitations_data = validated_data.pop('users_to_invite')
KeyError: 'users_to_invite'

How can I make the array to appear there? Modifying the model does not sound like a good idea because I don't want to store what's in the array.

extra data is absent in validated_data you can try use self.context['request'] details: including-extra-context , by default it added in the get_serializer method of view

for your case:

def create(self, validated_data):
    # Get user ids to invite
    # !! It fails here !!
    request = self.context['request']
    invitations_data = request.data.get('users_to_invite')

To send extra context data you should pass it from the method def get_serializer_context(self) and access inside serializer like self.context.get("key") .

sample code:

class GroupListView(ListCreateAPIView):
    queryset = Group.objects.all()

    def get_serializer_context(self):
        context = super(GroupListView, self).get_serializer_context()
        context["users_to_invite"] = request.data.get("users_to_invite")
        return context

class GroupCreateSerializer(ModelSerializer):

    def create(self, validated_data):
        users_to_invite = self.context.get("users_to_invite")
        # do whatever you want

Apart from adding the data to context, you can add the field users_to_invite to serializer as a CharField .

Example :

import json

class GroupCreateSerializer(ModelSerializer):

    def create(self, validated_data):
        # Get user ids to invite
        # !! It fails here !!
        invitations_data = json.loads(validated_data.pop('users_to_invite'))

        # TODO: Iterate over ids and create invitations

        # Create a group
        group = Group.objects.create(**validated_data)
        return group

    users_to_invite = serializers.CharField(required=False)

    class Meta:
        model = Group
        fields = ('id', 'name', 'users_to_invite', )

Note: Make sure to have users_to_invite in request data as a string. Like: '[1, 2, 3]'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM