Как добавить дополнительные поля в сериализатор модели в django ModelViewSet?

Классы сериализатора корзины

class CartSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)
    menuitem = MenuItemSerializer(read_only=True)
    price = serializers.SerializerMethodField(method_name='calculate_price')
    menuitem_id = serializers.IntegerField(write_only=True)
    user_id = serializers.IntegerField(write_only=True)

    class Meta:
        model = Cart
        fields = ['id', 'user', 'menuitem', 'quantity',
                  'unit_price', 'price', 'menuitem_id', 'user_id']
        validators = [
            validators.UniqueTogetherValidator(
                queryset=MenuItem.objects.all(),
                fields=('id',),
                message="Menuitem should be unique in this curt"
            ),
            validators.UniqueTogetherValidator(
                queryset=User.objects.all(), fields=('id'), message="User should be unique")
        ]

    def calculate_price(self, item: Cart):
        print(item.unit_price * item.quantity)
        return item.unit_price * item.quantity

Метод add_cart в классе CartItemsViewSet

 @action(detail=True, methods=['post'])
    def add_cart(self, request, pk=None):
        if request.user.is_authenticated:
            user = request.user
        else:
            return Response('User is not authenticated', 403)
        # print(request.data)
        # print(request.user.id)
        # user_id = user.id
        # menuitem_id = request.data['menuitem_id']
        # quantity = request.data['quantity']
        # unit_price = request.data['unit_price']
        # id = request.data['id']
        # pack_data = {'user_id': user_id, 'menuitem_id': menuitem_id,
        #              'quantity': quantity, 'unit_price': unit_price, 'id': id}

        serializer = serializers.CartSerializer(
            data=request.data)

        if serializer.is_valid(raise_exception=True):
            print(serializer.validated_data)
            serializer.save(user_id=user.id)
            return Response('Item is added successfully.', 201)

Модель корзины

class Cart(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    menuitem = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
    quantity = models.SmallIntegerField(),
    unit_price = models.DecimalField(max_digits=6, decimal_places=2)
    price = models.DecimalField(max_digits=6, decimal_places=2)

    class Meta:
        unique_together = ('menuitem', 'user')

Я хочу реализовать добавление пользователем пункта меню в корзину. Но проблема в том, что я не добавляю дополнительное поле 'user_id' При сохранении таблицы с помощью сериализатора было показано следующее сообщение об ошибке. { «user_id": [ «Это поле обязательно для заполнения». ] }

Error message

Причина, по которой drf выдает эту ошибку, даже если вы передаете user.id в метод save, заключается в ошибке, вызванной методом is_valid, который выполняется перед методом save, а ключ user не установлен в request.data.

Для передачи сериализатору зарегистрированного пользователя вы можете использовать это поле сериализатора:

user = serializers.HiddenField(default=serializers.CurrentUserDefault())

Это поле само получит пользователя из запроса.

Подсказка: Я думаю, вам следует пересмотреть вашу модель и уникальные ограничения (особенно ограничения в сериализаторе) Подсказка: HTTP-код статуса для отказа в аутентификации - 401, или если вы хотите вернуть код статуса 403, сообщение должно быть каким-то другим, например permission denied

user_id должен быть только для чтения, иначе он ожидает найти данные в запросе, так что:

class CartSerializer(serializers.ModelSerializer):
    # …
    user_id = serializers.IntegerField(read_only=True)
    # …

Вы записываете user_id через .save() сериализатор:

serializer.save(user_id=user.id)
Вернуться на верх