Как ответить на разные данные, которые были вставлены методом create (ModelViewSet) - PullRequest
6 голосов
/ 27 мая 2019

Я реализую менеджер стандартной обуви с архитектурой REST, используя Django + Django 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']

Метод retrieve (GET глагол) этой конечной точки ожидает сериализации данных с помощью ShoeSerializer, но метод custom_create вставляет данные с использованием StockPostSerializer. Как я могу вернуть ответ с другими данными, которые были вставлены?

Когда я пытаюсь вставить с этой конечной точкой, я получаю это сообщение об ошибке, но когда я обновляю страницу, я понимаю, что контент был вставлен (Если я использую почтальон вместо интерфейса de DRF, я не получаю никакого сообщение об ошибке, работает нормально).

Как мой метод custom_create может правильно реагировать?

Вы можете проверить мой github , имена будут немного отличаться, потому что я перевел это здесь, чтобы вам было легче понять.

PS : Как вы, наверное, заметили, я не являюсь носителем английского языка, поэтому мне очень трудно выразить себя здесь, но я стараюсь изо всех сил и учусь все больше и больше. Если мой вопрос содержит ошибки грамматики / соответствия, пожалуйста, исправьте их, но вам не нужно отказывать мне, поэтому я пытаюсь учиться!

Ответы [ 2 ]

4 голосов
/ 29 мая 2019

Мне наконец-то удалось разобраться в этом, и гораздо более элегантно, чем я пытался заранее.

Что мне нужно сделать, это добавить новые экземпляры акций, для этого я создал новыймаршрут для POST в ресурсах конечной точки / id.

Итак, я смог повторно использовать Маршрутизатор по умолчанию, удалить метод 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.Спасибо за поддержку!

2 голосов
/ 29 мая 2019

Если я правильно понял, посмотрев на ваш код, в данном случае, в частности, вам не нужен StockPostSerializer.Вы можете получить желаемый результат, изменив StockSerializer следующим образом:

class StockSerializer(serializers.ModelSerializer):

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

Я очень извиняюсь, если неправильно понял ваш вопрос.

РЕДАКТИРОВАТЬ:

Забыл сказать,При использовании этого сериализатора вам не нужен дополнительный маршрут на ModelViewSet

...