【发布时间】:2020-01-27 18:19:06
【问题描述】:
我正在学习 Django,所以这可能不是做我想做的最好的方式。
我在这里要做的是显示一个在购物车中被多次选择的项目,只显示一次(以及它旁边被选择的次数)
我整天都在寻找一种方法,但我设法做的最接近的事情是在视图内部生成两个集合:single_items 和 multiple_items。
显示只选择一次的项目没有问题,但是当涉及多次选择的项目时,我只能显示它们n次,旁边是出现的次数,如图所示
虽然我宁愿使用 python 代码(在 views.py 中)进行所有计算,但使用 Django 模板语言的解决方案会对我有用。
请考虑我需要在 url 中传递项目 ID 才能使删除链接起作用。
这里是views.py
from django.shortcuts import render, redirect
from .models import Cart, Item, CartItem
from django.db.models import Sum
# Create your views here.
def home(request):
items = Item.objects.all()
carts = Cart.objects.all()
length = len(Cart.objects.all())
cart = carts[length - 1]
cart_items = cart.items.all()
total = cart_items.aggregate(Sum('price'))['price__sum']
if total is None:
total = 0
number_of_items = cart_items.count()
deletable_items = CartItem.objects.all()
occurrences = None
single_items = set()
multiple_items = set()
for deletable_item in deletable_items:
occurrences = deletable_items.filter(item__name=deletable_item.item).count()
if occurrences > 1:
deletable_item.occurrences = occurrences
multiple_items.add(deletable_item)
elif occurrences == 1:
deletable_item.occurrences = occurrences
single_items.add(deletable_item)
return render(request, 'cart/home.html', {'cart': cart,
'items': items,
'cart_items': cart_items,
'total': total,
'number_of_items': number_of_items,
'deletable_items': deletable_items,
'multiple_items': multiple_items,
'single_items': single_items,
'occurrences': occurrences
})
def add_to_cart(request, item_id):
item_id = Item.objects.get(id=item_id)
carts = Cart.objects.all()
length = len(Cart.objects.all())
cart = carts[length - 1]
cart_item = CartItem.objects.create(item=item_id, cart=cart)
return redirect(home)
def remove_from_cart(request, item_id):
item_to_remove = CartItem.objects.get(id=item_id)
item_to_remove.delete(
)
return redirect(home)
还有我的模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home page</title>
</head>
<body>
<h1>My Restaurant</h1>
<div><h1>Menu</h1></div>
{% for item in items %}
<ul>{{ item }} £{{ item.price}} <a href="{% url 'add_to_cart' item.id %}">Add</a></ul>
{% endfor %}
<div><h1>Order</h1></div>
{{ cart }}
<br>
<h2>items selected: {{ number_of_items }}</h2>
{% for single_item in single_items %}
<ul>{{ single_item }} x {{ single_item.occurrences }} <a href="{% url 'remove_from_cart' single_item.id %}">Remove</a></ul>
{% endfor %}
{% for multiple_item in multiple_items %}
<ul>{{ multiple_item }} x {{ multiple_item.occurrences }} <a href="{% url 'remove_from_cart' multiple_item.id %}">Remove</a></ul>
{% endfor %}
<h2>Total</h2>
{{ total|floatformat:2 }}
</body>
</html>
以防万一模型
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Item(models.Model):
name = models.CharField(max_length=25)
price = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return self.name
class Cart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
items = models.ManyToManyField(Item, through='CartItem')
def __str__(self):
return 'Order number: %s' % self.id
class CartItem(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
def __str__(self):
return str(self.item)
编辑
目前我正在使用 Willem Van Onsem 建议的这个 view.py
from django.shortcuts import render, redirect
from .models import Cart, Item, CartItem
from django.db.models import Sum, Count, F
# Create your views here.
def home(request):
cart = Cart.objects.filter(user=request.user).last()
items = Item.objects.all()
cart_items = Item.objects.filter(
cartitem__cart=cart
).annotate(
ncount=Count('cartitem')
)
total = cart_items.aggregate(total=Sum(F('price') * F(float('ncount'))))['total']
context = {
'items': items,
'total': total,
'cart_items': cart_items
}
return render(request, 'cart/home.html', context)
def add_to_cart(request, item_id):
item_id = Item.objects.get(id=item_id)
carts = Cart.objects.all()
length = len(Cart.objects.all())
cart = carts[length - 1]
cart_item = CartItem.objects.create(item=item_id, cart=cart)
return redirect(home)
def remove_from_cart(request, item_id):
item_to_remove = CartItem.objects.get(id=item_id)
item_to_remove.delete()
return redirect(home)
【问题讨论】:
-
嗯,问题是你每次都计算项目的数量。但这些是不同
CartItems,因此set(..)确实不将它们视为不同的。 -
我想你想说 set() 确实将它们视为不同的,这就是允许重复的原因(它们是具有相同名称属性的不同对象)
-
carts[length-1]在做什么?如果有多个用户,他们将看到最后一个购物车,因此一个用户将看到另一个用户的购物车。 -
因为两个名字都以
Mirko为名的人,不本质上是同一个人。 -
只是为了获取创建的最后一个购物车(订单)...
标签: django django-templates django-views