#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 строки)