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

Back to Top