Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Django模板上仅显示集合中第一次出现的项?_Django_Django Templates_Django Views - Fatal编程技术网

如何在Django模板上仅显示集合中第一次出现的项?

如何在Django模板上仅显示集合中第一次出现的项?,django,django-templates,django-views,Django,Django Templates,Django Views,我正在学习Django,所以这可能不是我想要的最好的方法 我在这里尝试的是显示购物车中多次选择的项目,仅显示一次(以及在旁边选择的次数) 我一整天都在试图找到一种方法,但我能做的最接近的事情是,在视图中,生成两个集合:单个_项和多个_项 我在显示一个只被选中一次的项目时没有问题,但是当涉及到多次被选中的项目时,我只能显示n次,并且旁边出现的项目的数量,如图所示 尽管我更愿意使用python代码(在views.py中)进行所有计算,但使用Django模板语言的解决方案对我来说也行 请考虑在URL

我正在学习Django,所以这可能不是我想要的最好的方法

我在这里尝试的是显示购物车中多次选择的项目,仅显示一次(以及在旁边选择的次数)

我一整天都在试图找到一种方法,但我能做的最接近的事情是,在视图中,生成两个集合:单个_项和多个_项

我在显示一个只被选中一次的项目时没有问题,但是当涉及到多次被选中的项目时,我只能显示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>
编辑

目前,我正在使用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)

我认为最好在这里开发两个查询集,如:

from django.db.models import Count, F, Sum

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', output_field=DecimalField(max_digits=5, decimal_places=0))
    )
    total = cart_items.aggregate(total=Sum(F('price') * F('ncount')))['total']
    context = {
        'items': items,
        'total': total,
        'cart_items': cart_items
    }
    return return render(request, 'cart/home.html', context)
从django.db.models导入计数F和
def home(请求):
cart=cart.objects.filter(user=request.user).last()
items=Item.objects.all()
购物车\商品=Item.objects.filter(
cartitem\uuu cart=购物车
).注释(
ncount=Count('cartitem',output\u field=DecimalField(最大位数=5,小数位数=0))
)
总计=购物车项目。合计(总计=总和(F(‘价格’)*F(‘ncount’)[‘总计’]
上下文={
“项目”:项目,
“总计”:总计,
“购物车项目”:购物车项目
}
返回渲染(请求“cart/home.html”,上下文)
在模板中,您可以使用以下内容呈现购物车:

<h2>items selected: {{ cart_items|length }}</h2>
{% for item in cart_items %}
    <ul>{{ item }} x {{ item.ncount }} <a href="{% url 'remove_from_cart' item.id %}">Remove</a></ul>
{% endfor %}
<h2>Total</h2>
{{ total|floatformat:2 }}
所选项目:{{cart_items | length}
{购物车中商品的%u%}
    {item}x{{item.ncount}
{%endfor%} 全部的 {{total | floatformat:2}}
因此,没有理由区分一次性或多次购买的物品

您可以通过以下方式实现删除功能:

def remove_from_cart(request, item_id):
    cart = Cart.objects.filter(user=request.user).last()
    item_to_remove = CartItem.objects.filter(
        item_id=item_id,
        cart=cart
    ).delete()
    return redirect(home)
def从购物车中删除(请求,项目id):
cart=cart.objects.filter(user=request.user).last()
item_to_remove=CartItem.objects.filter(
项目标识=项目标识,
购物车
)1.删除()

return redirect(home)
我认为在这里最好开发两个查询集,如:

from django.db.models import Count, F, Sum

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', output_field=DecimalField(max_digits=5, decimal_places=0))
    )
    total = cart_items.aggregate(total=Sum(F('price') * F('ncount')))['total']
    context = {
        'items': items,
        'total': total,
        'cart_items': cart_items
    }
    return return render(request, 'cart/home.html', context)
从django.db.models导入计数F和
def home(请求):
cart=cart.objects.filter(user=request.user).last()
items=Item.objects.all()
购物车\商品=Item.objects.filter(
cartitem\uuu cart=购物车
).注释(
ncount=Count('cartitem',output\u field=DecimalField(最大位数=5,小数位数=0))
)
总计=购物车项目。合计(总计=总和(F(‘价格’)*F(‘ncount’)[‘总计’]
上下文={
“项目”:项目,
“总计”:总计,
“购物车项目”:购物车项目
}
返回渲染(请求“cart/home.html”,上下文)
在模板中,您可以使用以下内容呈现购物车:

<h2>items selected: {{ cart_items|length }}</h2>
{% for item in cart_items %}
    <ul>{{ item }} x {{ item.ncount }} <a href="{% url 'remove_from_cart' item.id %}">Remove</a></ul>
{% endfor %}
<h2>Total</h2>
{{ total|floatformat:2 }}
所选项目:{{cart_items | length}
{购物车中商品的%u%}
    {item}x{{item.ncount}
{%endfor%} 全部的 {{total | floatformat:2}}
因此,没有理由区分一次性或多次购买的物品

您可以通过以下方式实现删除功能:

def remove_from_cart(request, item_id):
    cart = Cart.objects.filter(user=request.user).last()
    item_to_remove = CartItem.objects.filter(
        item_id=item_id,
        cart=cart
    ).delete()
    return redirect(home)
def从购物车中删除(请求,项目id):
cart=cart.objects.filter(user=request.user).last()
item_to_remove=CartItem.objects.filter(
项目标识=项目标识,
购物车
)1.删除()

return redirect(home)
如果您甚至在用户签出之前就在数据库中保存所选项目,我不建议这样做,那么您可以在模型中进行类似的操作

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)
class Product(models.Model):
    #model info


class Order(models.Model):
    item = modelS.ForeignKey(Product, on_delete=models.CASCADE)
    user = modelS.ForeignKey(User, on_delete=models.CASCADE)
    times = models.IntagerField(default=1)
    #..... other relevant fields

class Cart(models.Model):
    orders = models.ManyToManyField(Order)
    user = modelS.ForeignKey(User,related_name='cart_user' on_delete=models.CASCADE)
    #other details like date etc....

然后是一个检查模型是否已存在的视图

def add_order(request,id):
    user = request.user
    item = Product.objects.get(id=id)
    try:
       order = Order.objects.get(item=item, user=user)
       order.times+=1
       order.save()
    except:
      order = Order.objects.create(
             item = item,
             user = user
            )
     try:
         my_cart = Cart.objects.get(user=user)
     except:
         my_cart = Cart.objects.create(user=user)
     my_cart.orders.add(order)

   #return http reeponse with the new data


我建议您使用ajax将请求提交到调用视图更新的url,以便在将来减少页面刷新

如果您甚至在用户签出之前就在数据库中保存所选项目(我不建议这样做),那么您可以在模型中执行类似操作

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)
class Product(models.Model):
    #model info


class Order(models.Model):
    item = modelS.ForeignKey(Product, on_delete=models.CASCADE)
    user = modelS.ForeignKey(User, on_delete=models.CASCADE)
    times = models.IntagerField(default=1)
    #..... other relevant fields

class Cart(models.Model):
    orders = models.ManyToManyField(Order)
    user = modelS.ForeignKey(User,related_name='cart_user' on_delete=models.CASCADE)
    #other details like date etc....

然后是一个检查模型是否已存在的视图

def add_order(request,id):
    user = request.user
    item = Product.objects.get(id=id)
    try:
       order = Order.objects.get(item=item, user=user)
       order.times+=1
       order.save()
    except:
      order = Order.objects.create(
             item = item,
             user = user
            )
     try:
         my_cart = Cart.objects.get(user=user)
     except:
         my_cart = Cart.objects.create(user=user)
     my_cart.orders.add(order)

   #return http reeponse with the new data


我建议您使用ajax将请求提交到调用视图更新的url,以便在将来减少页面刷新次数。这只是另一种方法:为什么不在models.py中为CartItem模型添加一个名为“quantity”的字段或类似的字段?例如:

class CartItem(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=0)
然后在“添加到购物车”视图中,执行以下操作:

def add_to_cart(request, item_id):
    item = Item.objects.get(id=item_id)
    cart = Cart.objects.filter(user=request.user).last()
    cart_item_qs = CartItem.objects.filter(cart__pk=cart.pk)
    if cart_item_qs.exists():
        cart_item_qs.update(quantity=F('quantity') + 1)
    else:
        cart.items.add(item)
        cart.save()

    return redirect(home)

之后,您可以在模板中使用CartItem模型的实例在上下文数据中传递它,从而从那里访问quantity字段值。

另一种方法:为什么不在models.py中为CartItem模型添加一个名为“quantity”的字段或类似的内容?例如:

class CartItem(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=0)
然后在“添加到购物车”视图中,执行以下操作:

def add_to_cart(request, item_id):
    item = Item.objects.get(id=item_id)
    cart = Cart.objects.filter(user=request.user).last()
    cart_item_qs = CartItem.objects.filter(cart__pk=cart.pk)
    if cart_item_qs.exists():
        cart_item_qs.update(quantity=F('quantity') + 1)
    else:
        cart.items.add(item)
        cart.save()

    return redirect(home)

之后,您可以在模板中使用CartItem模型的实例在上下文数据中传递它,从而从那里访问quantity字段值。

问题是,您每次都要计算项目的数量。但是它们是不同的
CartItem
s,因此
set(…)
不会将它们视为不同的。我想你应该说set()会将它们视为不同的,这就是为什么允许重复(它们是具有相同名称属性的不同对象)的原因
carts[length-1]
在做什么?如果有多个用户,他们将看到最后一个购物车,因此一个用户将看到另一个用户的购物车。因为两个人的名字都是
Mirko
,本质上不是同一个人。只是为了得到创建的最后一个购物车(订单)…问题是你每次都要计算物品的数量。但是这些是不同的
CartItem
s,因此
集合(…)
没有看到