1👍
An approach I can think of is to use django’s in_bulk
, to populate a dictionary that uses the asset type name as key and the asset type instance as value:
# This will create {'asset_type_name': asset_type_instance} mapping
asset_types = AssetType.objects.in_bulk(field_name='name')
Then pass it to the serializer as context:
serializer = AssetSerializer(
data=request.data['data'], many=True,
context={'asset_types_map': asset_types},
)
serializer.is_valid(raise_exception=True)
serializer.save()
And then use the map on a custom create, using the asset type name in the data to get the asset type instance like this:
class AssetSerializer(serializers.ModelSerializer):
asset_type_name = serializers.CharField(source='asset_type.name')
class Meta:
model = Asset
fields = ("id", "asset_type_name", "asset_name", "display_name")
def create(self, validated_data):
asset_type_name = validated_data.pop('asset_type_name')
validated_data['asset_type'] = self.context['asset_types_map'].get(asset_type_name)
return super().create(validated_data)
Haven’t tested this so might fail here and there, but the gist is here.
0👍
Answering my own question for anyone in the future having the same problem.
Heavily inspired by @bdbd’s answer but didn’t need the dictionary or the context part.
Here is the code which worked:
The viewset was fairly simple. Accept request data and pass to serializer
class AssetViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Asset.objects.select_related()
serializer_class = AssetSerializer
@action(methods=['POST'], detail=False)
def bulk_create(self, request):
serializer = AssetSerializer(
data=request.data['data'], many=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
In the serializer, query the asset type object from the name and send it as a part of creating asset object.
class AssetSerializer(serializers.ModelSerializer):
asset_type_name = serializers.CharField(source='asset_type.name')
class Meta:
model = Asset
fields = ("id", "asset_type_name", "asset_name", "display_name")
def create(self, validated_data):
asset_type = validated_data.pop('asset_type')
asset_type = AssetType.objects.get(**asset_type)
return Asset.objects.create(**validated_data, asset_type=asset_type)
Update
Based on the comment below by @bdbd,
this method works but in_bulk
saves the number of queries to the db so that is more preferable to use.
Leaving this answer here just in case.
- [Answered ]-Django login_required decorator not passing "next" value to template
- [Answered ]-With Django REST framework, how do I parse a RESTful string parameter?
- [Answered ]-Retrieve Django ManyToMany results outside of the current model
- [Answered ]-How to not start an EmberJs App with static assets present