Cannot assign "OrderItem.product" must be a "Product" instance
I am trying to create a "create order" endpoint, i keep getting
Cannot assign "<django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x7f50dad00f70>": "OrderItem.product" must be a "Product" instance.
heres my models
def product_images(instance, filename):
return f"product/{instance.product_name}/{filename}"
class Product(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=200, null=True, blank=True)
description = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
image = models.ImageField(
storage=MediaRootS3BotoStorage(),
upload_to="product_images",
null=True,
blank=True,
)
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return self.name
def save(self, *args, **kw):
self.slug = slugify(f"{self.name}")
super(Product, self).save(*args, **kw)
# Ecommerce Models Store and Product
def store_images(instance, filename):
return f"{instance.store_name}/{filename}"
class Store(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=200, null=True, blank=True)
description = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
image = models.ImageField(upload_to="store_images", null=True, blank=True)
delivery_fee = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
address = models.CharField(max_length=100, null=True, blank=True)
phone_number = models.CharField(max_length=100, null=True, blank=True)
products = models.ManyToManyField("Product", through="StoresProduct")
def __str__(self):
return self.name
def save(self, *args, **kw):
self.slug = slugify(f"{self.name}")
super(Store, self).save(*args, **kw)
class Cart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ManyToManyField("Product", through="StoresProduct")
quantity = models.IntegerField(default=1)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user.email
def get_total(self):
return self.product.price * self.quantity
class StoresProduct(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
seller = models.ForeignKey(Store, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
quantity = models.IntegerField(blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
cart = models.ForeignKey(
Cart,
on_delete=models.CASCADE,
related_name="products",
default=None,
null=True,
blank=True,
)
product = models.ForeignKey(
Product,
on_delete=models.CASCADE,
related_name="+",
default=None,
null=True,
blank=True,
)
def __str__(self):
return f"{self.product.name} - {self.seller.name}"
class Meta:
unique_together = ["product", "seller"]
OrderStatus = (
("Pending", "Pending"),
("Delivered", "Delivered"),
("Cancelled", "Cancelled"),
("Processing", "Processing"),
)
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=100, choices=OrderStatus, default="Pending")
delivery_fee = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
total = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
order_id = models.CharField(max_length=100, null=True, blank=True)
order_items = models.ManyToManyField("Product", through="OrderItem")
store = models.ForeignKey(Store, on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return self.user.email + " - " + self.order_id
def get_random_order_id(self):
order_id = str(uuid.uuid4()).replace("-", "").upper()[:10]
return order_id
# create order id with random string
def save(self, *args, **kwargs):
if not self.order_id:
self.order_id = self.get_random_order_id()
super(Order, self).save(*args, **kwargs)
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
order = models.ForeignKey(Order, on_delete=models.CASCADE)
store = models.ForeignKey(Store, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.product.name
and my views.py
#create order with orderitems
@swagger_auto_schema(method="post", request_body=OrderSerializer)
@api_view(["POST"])
@permission_classes((permissions.AllowAny,))
@authentication_classes([TokenAuthentication])
def create_order(request):
"""
Creates an order then creates an orderitem
"""
user = request.user
serializer = OrderSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=user)
order_id = serializer.data["id"]
order = Order.objects.get(pk=order_id)
cart = user.cart_set.all()
for item in cart:
OrderItem.objects.create(
order=order,
product=item.product,
quantity=item.quantity,
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@swagger_auto_schema(method="post", request_body=AddToCartSerializer)
@api_view(["POST"])
@permission_classes((permissions.AllowAny,))
@authentication_classes([TokenAuthentication])
def add_to_cart(request):
"""
Adds a product to cart
"""
user = request.user
serializer = AddToCartSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Basically, users should be able to add products from various stores to their cart and when they are done they should be able to order. I can't seem to figure out what i am doing wrongly, if there's a better way to do this do tell.I'm guessing my approach is problematic