Failed to get non-model field in validated_data of Django Rest Framework serializer

I have an ItemCollection and Items in my Django models, and I want to be able to remove items from the collection through the user interface. In the REST PUT request, I add an additional logical field deleted for each element to signal that the element should be deleted.

The correct way to handle this seems to be in the Serializer update method. My problem is that this non-modeled deleted field is deleted during validation, so it is no longer available. Adding deleted as a SerializerMethodField did not help. At the moment, I am getting deleted information from the initial_data attribute of the Serializer, but this does not seem correct.

My current sample code is below. Does anyone know a better approach?

Models:

  class ItemCollection(models.Model): description = models.CharField(max_length=256) class Item(models.Model): collection = models.ForeignKey(ItemCollection, related_name="items") 

serializers:

  from django.shortcuts import get_object_or_404 from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from models import Item, ItemCollection class ItemSerializer(serializers.ModelSerializer): class Meta: model = Item class ItemCollectionSerializer(serializers.ModelSerializer): items = ItemSerializer(many=True, read_only=False) class Meta: model = ItemCollection def update(self, instance, validated_data): instance.description = validated_data['description'] for item, item_obj in zip( self.initial_data['items'], validated_data['items']): if item['delete']: instance.items.filter(id=item['id']).delete() return instance class ItemCollectionView(APIView): def get(self, request, ic_id): item_collection = get_object_or_404(ItemCollection, pk=ic_id) serialized = ItemCollectionSerializer(item_collection).data return Response(serialized) def put(self, request, ic_id): item_collection = get_object_or_404(ItemCollection, pk=ic_id) serializer = ItemCollectionSerializer( item_collection, data=request.data) if serializer.is_valid(raise_exception=True): serializer.save() return Response(serializer.data) 

And json example in PUT request:

  { "id": 2, "items": [ { "id": 3, "collection": 2, "delete": true } ], "description": "mycoll" } 
+5
source share
1 answer

You can add non-model fields back by overwriting to_internal_value fn:

 def to_internal_value(self, data): internal_value = super(MySerializer, self).to_internal_value(data) my_non_model_field_raw_value = data.get("my_non_model_field") my_non_model_field_value = ConvertRawValueInSomeCleverWay(my_non_model_field_raw_value) internal_value.update({ "my_non_model_field": my_non_model_field_value }) return internal_value 

Then you can process it as you want in create or update .

+13
source

All Articles