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

时间:2019-05-26 22:00:08

标签: django django-rest-framework

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

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

我在/resources/id端点中添加了另一个动词POST,该动词由custom_create方法调用。

在这里您可以看到此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)

我需要这样做,因为我有两个模型,下面可以看到我的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']

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

当我尝试使用此端点插入时,我收到this错误消息,但是当我刷新页面时,我意识到内容已插入(如果我使用邮递员而不是de DRF前端,则不会收到任何错误消息,效果很好)。

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

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

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

2 个答案:

答案 0 :(得分:1)

如果通过查看您的代码我能正确理解,那么在这种情况下,则不需要StockPostSerializer。您可以通过如下更改StockSerializer来获得所需的结果:

class StockSerializer(serializers.ModelSerializer):

    class Meta:
        model = Stock
        fields = ['shoe', 'size', 'amount']
        extra_kwargs = {'shoe': {'write_only': True}}

如果我误解了你的问题,我深表歉意。

编辑:

忘了说。使用此序列化程序,您的ModelViewSet

不需要任何额外的路由

答案 1 :(得分:0)

我终于设法解决了这个问题,并且比以前尝试的要优雅得多。

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

因此,我能够重用默认路由器,删除custom_create方法,并修改了serializers.py文件。 看起来像这样:

serializers.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']

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