I have an add-to-cart function that throws an error when It is triggered. The function works if a user uses the admin account, but when a user has a normal account, it shows the below error.
Views.py
@login_required
def add_to_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
order_item, created = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False,
)
order_qs = Order.objects.filter(user=request.user, ordered=False)
if order_qs.exists():
order = order_qs[0]
# check if the order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item.quantity += 1
order_item.save()
order.save()
messages.success(request, "This item was updated to your cart.")
else:
messages.success(request, "This item was added to your cart.")
order.items.add(order_item)
order.save()
else:
ordered_date = timezone.now()
order = Order.objects.get_or_create(id=item.id,
user=request.user, ordered_date=ordered_date)
order.items.add(order_item)
order.save()
messages.success(request, "This item was added to your cart.")
return redirect("product", slug=slug)
Models.py
class Item(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
price = models.FloatField()
stored = models.DateTimeField(auto_now_add=True)
item_quantity = models.IntegerField(default=1)
img = models.ImageField(upload_to='images/')
category = models.CharField(choices=CATEGORY_CHOICES, max_length=15)
slug = models.SlugField(unique=True, default=uuid.uuid1)
def __str__(self) -> str:
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse("product", kwargs={"slug": self.slug})
def get_add_to_cart_url(self):
return reverse("add-to-cart", kwargs={
'slug': self.slug
})
def get_remove_from_cart_url(self):
return reverse("remove_from_cart", kwargs={
'slug': self.slug
})
def get_add_single_item_to_cart_url(self):
return reverse("add_single_item_to_cart", kwargs={
'slug': self.slug
})
def get_remove_single_item_from_cart_url(self):
return reverse("remove_single_item_from_cart", kwargs={
'slug': self.slug
})
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
ordered = models.BooleanField(default=False)
def __str__(self):
return f"{self.quantity} of {self.item.title}"
def get_total_item_price(self):
return self.quantity * self.item.price
def get_final_price(self):
return self.get_total_item_price()
def get_quantity(self):
return self.quantity
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add=True)
ordered_date = models.DateTimeField()
ordered = models.BooleanField(default=False)
total_price = models.FloatField(default=0)
def __str__(self):
return self.user.username
def get_total(self):
total = 0
for order_item in self.items.all():
total += order_item.get_final_price()
return total
def save(self, *args, **kwargs):
total = 0
self.total_price = self.get_total()
return super().save(*args, **kwargs)
Error message:
IntegrityError at /add-to-cart/start-with-why/ UNIQUE constraint failed: ecommpage_order.id Request Method: GET Request URL: http://127.0.0.1:8000/add-to-cart/start-with-why/ Django Version: 3.1.7 Exception Type: IntegrityError Exception Value: UNIQUE constraint failed: ecommpage_order.id
You create an order with id=item.id
, but that makes not much sense since the database normally dispatches the id. Especially since you set the id of the order, this means that it is likely that eventually the same id will be used.
You thus should remove
order = Order.objects.get_or_create(
id=item.id,
user=request.user,
ordered_date=ordered_date
)
and simply create an Order
and then add an item to that order:
order = Order.objects.get_or_create(
user=request.user,
ordered_date=ordered_date
)
orderorder_item
The modeling also looks a bit odd. Normally the quantity is stored in the junction table [wiki] . You can do that in Django by specifying a through=…
model [Django-doc] .
Note : Django's
DateTimeField
[Django-doc] has aauto_now_add=…
parameter [Django-doc] to work with timestamps. This will automatically assign the current datetime when creating the object, and mark it as non-editable (editable=False
), such that it does not appear inModelForm
s by default.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.