如何响应创建方法(ModelViewSet)插入的不同数据

Tâm*_*iro 6 django django-rest-framework

我正在使用Django + Django rest用REST架构实现股票经理。

我使用从DefaultRouter继承的自定义路由器为我的端点提供服务。

/resources/idIve 在端点中又添加了一个动词,POST该动词由custom_createmethod 调用。

在这里您可以看到此custom_create方法:

viewsets.py


class ShoeViewSet(viewsets.ModelViewSet):

    queryset = Shoe.objects.all()
    filter_class = ShoeFilter

    def get_serializer_class(self):
        if self.action == 'custom_create':
            return StockPostSerializer
        else:
            return ShoeSerializer

    def custom_create(self, request, *args, **kwargs):
        data = {}

        data['shoe'] = kwargs['pk']
        data['size'] = request.data.get('size')
        data['amount'] = request.data.get('amount')

        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)

        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Run Code Online (Sandbox Code Playgroud)

我需要这样做是因为我有两个模型,在下面可以看到我的3个序列化器:

serializers.py

class StockSerializer(serializers.ModelSerializer):

    class Meta:
        model = Stock
        fields = ['size', 'amount']

class ShoeSerializer(serializers.ModelSerializer):
    stock = StockSerializer(many=True, read_only=True)

    class Meta:
        model = Shoe
        fields = ['description', 'provider', 'type', 'cost_price','sale_price','total_amount', 'stock']

class StockPostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Stock
        fields = ['shoe','size', 'amount']
Run Code Online (Sandbox Code Playgroud)

此终结点的retrieveGET动词)方法需要使用序列化的数据ShoeSerializer,但是该custom_create方法使用插入数据StockPostSerializer。如何返回插入了其他数据的响应?

当我尝试使用此端点进行插入时,会收到错误消息,但是当我刷新页面时,我意识到内容已插入(如果我使用邮递员而不是de DRF前端,则不会收到任何错误消息,可以正常工作)。

我的custom_create方法如何正确响应?

您可以检查我的github,名称会有所不同,因为我在这里翻译了它,以便您轻松理解。

PS:您可能已经注意到,我不是英语母语人士,所以在这里表达自己的观点非常困难,但是我正在尽我所能,并且学习越来越多。如果我的问题包含语法/一致性错误,请更正它们,但您不必拒绝我,因此我正在尝试学习!

Tâm*_*iro 4

我终于设法解决了这个问题,并且以一种比我之前尝试过的更加优雅的方式。

我需要做的是:添加新的库存实例,为此我在端点资源/id 中为 POST 创建了一条新路由。

所以我能够重用默认路由器,删除custom_create方法,然后修改serializer.py 文件。它看起来像这样:

序列化器.py

class StockSerializer(serializers.ModelSerializer):

    class Meta:
        model = Stock
        fields = ['size', 'amount']

class ShoeSerializer(serializers.ModelSerializer):

    stock = StockSerializer(many=True)

    def update(self, instance, validated_data):
        instance.description   = validated_data.get(
            'description', instance.description)
        instance.provider  = validated_data.get(
            'provider', instance.provider)
        instance.type        = validated_data.get('type', instance.type)
        instance.cost_price = validated_data.get(
            'cost_price', instance.cost_price)
        instance.salve_price = validated_data.get(
            'sale_price', instance.sale_price)

        stock      = instance.stock.all()
        stock_data = validated_data.get('stock', [])

        for item_data in stock_data:
            item_id = item_data.get('size', None)
            if item_id is not None:
                item_db            = stock.get(size=item_id)
                item_db.size    = item_data.get('size', item_db.size)
                item_db.amount = item_data.get('amount',item_db.amount)
                item_db.save()
            else:
                Estoque.objects.create(
                    shoe = instance,
                    size    = item_data['size'],
                    amount = item_data['amount']
                )
        instance.save()
        return instance

    class Meta:
        model = Shoe
        fields = ['_id','description', 'provider', 'type', 'cost_price','sale_price','total_amount', 'stock']

Run Code Online (Sandbox Code Playgroud)

现在,通过PATCH动词我可以添加新的 Stock 实例并更改现有的 Stock 实例。谢谢你的支持!