Аргумент DRF: int() должен быть строкой, байтоподобным объектом или числом, а не атрибутом ‘DeferredAttribute’

#python #django #django-rest-framework

Вопрос:

Я создаю api электронной коммерции с использованием платформы Django Rest.

Это моя модель заказа. У меня есть 2 поля «много — много» для адресов и заказов.

 class Order(models.Model):
    payment_options= (
        ('COD', 'Cash on Delivery'),
        ('BANK', 'Bank Transfer'),
        ('WALLET', 'Wallet Transfer'),
    )
    delivery_options= (
        ('Placed', 'Placed'),
        ('Processing', 'Processing'),
        ('Delivered', 'Delivered'),
        ('Cancelled', 'Cancelled'),
    )
    order_number = models.AutoField(primary_key=True)
    items =  models.ManyToManyField(OrderItem)
    order_address = models.ManyToManyField(Address)
    delivery_date = models.DateTimeField(auto_now_add=False)
    price = models.FloatField()
    payment_method = models.CharField(max_length=6, choices=payment_options)
    delivery_status = models.CharField(max_length=16, choices=delivery_options, default='Placed')

    class Meta:
        ordering = ['order_number']

    def __str__(self):
        ord = str(self.order_number)
        ord_text = "Order #" ord
        return ord_text
 

Вот мой сериализатор:

 class OrderItemSerializer(serializers.ModelSerializer):

    prod = ProductSerializer()

    class Meta:
        model = OrderItem
        fields = ["quantity", "prod"]

class AdressSerializer(serializers.ModelSerializer):

    class Meta:
        model = Address
        fields =[
            "address_1",
            "address_2",
            "city",
            "state",
            "postcode",
            "country"
        ]

class CompleteOrderSerializer(serializers.ModelSerializer):
    items = OrderItemSerializer(many=True)
    order_address = AdressSerializer(many=True)
    
    class Meta:
        model = Order
        fields =[
            "order_number",
            "items",
            "delivery_date",
            "price",
            "payment_method",
            "delivery_status",
            "order_address",
        ]

    def create(self, validated_data):
        ord_id = []

        address_data = validated_data.pop('order_address')
        print(address_data)
        for j in range(len(address_data)):
            address = Address.objects.create(
                address_1=address_data[j]['address_1'],
                address_2=address_data[j]['address_2'],
                city=address_data[j]['city'],
                state = address_data[j]['state'],
                postcode=address_data[j]['postcode'],
                country=address_data[j]['country']
            )
            ord_id.append(address.id)

        item = validated_data.pop('items')

        ids = []
        
        for i in range(len(item)):
            prod = item[i]['prod']['name']
            count = item[i]['quantity']
        
            product = OrderItem.objects.create(
                prod=Product.objects.get(name=prod), 
                quantity=count
            )

            ids.append(product.id)

        Order.order_address = Address.objects.filter(id__in=(ord_id))
        Order.items = OrderItem.objects.filter(id__in=(ids))
        Order.objects.create(**validated_data)
        return Order 
 

А также ОТПРАВЛЯТЬ и ПОЛУЧАТЬ запросы

 class OrderApiView(APIView):
    """
    A simple ViewSet for viewing and posting orders.
    """
    def get(self, request):
        order = Order.objects.all()
        serializer = CompleteOrderSerializer(order, many=True)
        return Response(serializer.data)
    
    def post(self, request):
        data = JSONParser().parse(request)
        serializer = CompleteOrderSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return JsonResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
 

Большое вам спасибо за любую вашу помощь. Всякий раз, когда я делаю запрос на публикацию, данные сохраняются в базе данных, но когда дело доходит до отображения ответа на публикацию, в нем говорится

 int() argument must be a string, a bytes-like object or a number, not 'DeferredAttribute' .
 

В чем здесь проблема?

Ответ №1:

Попробуйте использовать этот фиксированный сериализатор

 class CompleteOrderSerializer(serializers.ModelSerializer):
    items = OrderItemSerializer(many=True)
    order_address = AdressSerializer(many=True)
    
    class Meta:
        model = Order
        fields =[
            "order_number",
            "items",
            "delivery_date",
            "price",
            "payment_method",
            "delivery_status",
            "order_address",
        ]

    def create(self, validated_data):
        addresses = []

        address_data = validated_data.pop('order_address')
        print(address_data)
        for add_d in address_data:
            address = Address.objects.create(
                address_1=add_d['address_1'],
                address_2=aadd_d['address_2'],
                city=add_d['city'],
                state = add_d['state'],
                postcode=add_d['postcode'],
                country=add_d['country']
            )
            # if your address_data only includes required data you can do this instead
            # address = Address.objects.create(**add_d)
            addresses.append(address)

        items = validated_data.pop('items')

        order_items = []
        for item in items:
            prod = Product.objects.get(name=item['prod']['name']) # if you have the prod id it's better to use than to look up by name
            quantity = item['quantity']
        
            order_item = OrderItem.objects.create(
                prod=prod, 
                quantity=quantity
            )
            order_items.append(order_item)


        order = Order.objects.create(**validated_data)
        order.items.set(order_items)
        order.order_address.set(addresses)
        return order 
 

Я не понимаю, почему у вас может быть несколько адресов для одного и того же заказа, может быть, это ошибка с вашей стороны или функция ?
Вы также пытались установить Order.order_address , какая операция недопустима, вам нужно будет создать новый объект заказа и предоставить ему необходимые данные.
Кроме того, поскольку вы создаете связанные объекты, у вас есть доступ к ним, поэтому нет необходимости отслеживать идентификаторы, а затем извлекать их снова.

обратите внимание, что вы также можете использовать другие сериализаторы для создания своих объектов (если вы хотите это сделать) вместо model.Objects.Create , например

 address = AdressSerializer(
        address_1=add_d['address_1'],
        address_2=aadd_d['address_2'],
        city=add_d['city'],
        state = add_d['state'],
        postcode=add_d['postcode'],
        country=add_d['country']
    )
 

что полезно, если вам также нужно переопределить метод сериализатора create для них

Комментарии:

1. Большое тебе спасибо, Джиммар. Но это снова показывает, что «Прямое назначение на переднюю сторону набора» многие ко многим » запрещено. Вместо этого используйте items.set ().»

2. @KanchanBhatta моя ошибка, я обновил ответ (изменил последние 4 строки)