首页 > 解决方案 > django forloop 计数器作为变量

问题描述

所以我正在尝试制作一个电子商务披萨网站,当用户将商品添加到购物篮时,它会以 cookie 的形式存储 cart=[{"id":"2","quantity":"1"},{"id":"3","quantity":"5"},{"id":"5","quantity":"3"},{"id":"5","quantity":"3"}]

我的views.py是...

def cart(request):
    cart = request.COOKIES.get('cart')
    cart = json.loads(cart)

    items =[]
    basket=[]
    for i in cart:
        pizza = Product.objects.filter(pk=i['id']).first()
        basket.append(int(i['quantity']))
        items.append(pizza)

    cart = len(cart)

    context = {
        "cart":cart,
        "pizzas":items,
        "basket":basket
    }
    return render (request, "store/cart.html", context)

我的models.py是...

class Product(models.Model):
    name = models.CharField(max_length=70)
    price = models.IntegerField()
    description = models.CharField(max_length=300)
    image = models.ImageField(upload_to="pizza_images")

    def save(self, *args, **kwargs):
        super().save()
        img = Image.open(self.image.path)

        img.save(self.image.path)

    def __str__(self):
        return f"{self.name}"

其中我的模板代码...

 <table>
            <thead>
                <tr>
                    <th scope="col" class="small_col">Item</th>
                    <th id="product_col" scope="col">Product</th>
                    <th scope="col" class="small_col">Quantity</th>
                    <th scope="col" class="small_col">Price</th>
                </tr>
            </thead>

            <tbody>
                {% for pizza in pizzas %}

                    <tr>
                        <td class="center">{{forloop.counter}}</td>
                        <td>{{pizza.name}}</td>
                        <td class="quantity_row justify-content-center">
                            <input class="quantity_input" type="text" value="{{basket.forloop.counter0}}" id="pizza{{forloop.counter}}">
                            <div class="form_buttons">
                                <img onclick="add(this.getAttribute('data-attribute'))" data-attribute="pizza{{forloop.counter}}" src="https://s.svgbox.net/hero-outline.svg?ic=plus-sm&fill=000" >
                                <img onclick="minus(this.getAttribute('data-attribute'))" data-attribute="pizza{{forloop.counter}}" src="https://s.svgbox.net/hero-outline.svg?ic=minus-sm&fill=000">
                            </div>
                        </td>
                        <td class="center">
                            <h6>$25</h6>
                        </td>
                        <td class="small_col">
                            <a><img class="mb-1" src="https://s.svgbox.net/hero-outline.svg?ic=trash&fill=d90429" width="20" height="20"></a>
                        </td>
                    </tr>
                        
                {% endfor %}

            </tbody>

        </table>

在输入字段中,我希望显示产品的数量。说...的那一行, <input class="quantity_input" type="text" value="{{basket.forloop.counter0}}" id="pizza{{forloop.counter}}">出于某种原因, forloop.counter 没有得到列表的值并使其为空。

关于如何让它发挥作用的任何想法?谢谢!

标签: pythondjangodjango-templates

解决方案


{{ basket.forloop.counter0 }}不起作用,因为这只会查看是否basket具有forloop 属性item,但事实并非如此,因为两者basket.forloopbasket['forloop']都会引发错误。

这也不是一个好主意,您在这里所做的是在模板中编写业务逻辑。模板应该只包含渲染逻辑:解释如何以令人愉悦的方式渲染数据的逻辑,而不是渲染的数据。

您可以使用zip(…)[python-doc]生成项目的 2 元组,然后在模板中枚举这些 2 元组:

def cart(request):
    cart = request.COOKIES.get('cart')
    cart = json.loads(cart)

    items = []
    basket = []
    for i in cart:
        pizza = Product.objects.filter(pk=i['id']).first()
        basket.append(int(i['quantity']))
        items.append(pizza)
    cart = len(cart)

    context = {
        "cart":cart,
        'pizzabaskets': zip(items, basket),
    }
    return render (request, 'store/cart.html', context)

然后用以下方式渲染它:

{% for pizza, basket in pizzabaskets %}
  <tr>
    <td class="center">{{forloop.counter}}</td>
    <td>{{pizza.name}}</td>
    <td class="quantity_row justify-content-center">
      <input class="quantity_input" type="text" value="{{basket}}" id="pizza{{forloop.counter}}">
      <div class="form_buttons">
        <img onclick="add(this.getAttribute('data-attribute'))" data-attribute="pizza{{forloop.counter}}" src="https://s.svgbox.net/hero-outline.svg?ic=plus-sm&fill=000" >
        <img onclick="minus(this.getAttribute('data-attribute'))" data-attribute="pizza{{forloop.counter}}" src="https://s.svgbox.net/hero-outline.svg?ic=minus-sm&fill=000">
      </div>
    </td>
    …
{% endfor %}

将其存储为 cookie 的篮子。

我建议不要使用 cookie。用户很容易通过伪造请求来操纵 Cookie。因此,这意味着用户可以更改 cookie,例如使用

[{"id":"2","quantity":"-10"},{"id":"3","quantity":"5"},{"id":"5","quantity":"3"}]

所以一个人可以订购负数量的比萨来降低价格。用户可以自由提交不同的结构并尝试寻找漏洞。如果您想将数据附加到会话,最好使用会话变量[Django-doc],因为它们存储在服务器端。


推荐阅读