Reputation: 390
So I am trying to make an e-commerce pizza site where when a user adds an item to the basket it is stored as a cookie in the form
cart=[{"id":"2","quantity":"1"},{"id":"3","quantity":"5"},{"id":"5","quantity":"3"},{"id":"5","quantity":"3"}]
And my views.py is...
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)
And my models.py is ...
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}"
In which my template code...
<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>
And in the input field I want the quantity of the product to be displayed. The line which says...
<input class="quantity_input" type="text" value="{{basket.forloop.counter0}}" id="pizza{{forloop.counter}}">
and for somereason the forloop.counter doesn't get the the value of the list and makes it null.
Any ideas on how i could make it work? Thanks!
Upvotes: 2
Views: 1894
Reputation: 476614
{{ basket.forloop.counter0 }}
will not work, since this simply will look if basket
has a forloop
attribute or item, but that is not the case, since both basket.forloop
and basket['forloop']
will raise an error.
It is also not a good idea, what you do here is writing business logic in the template. A template should only contain rendering logic: logic that explains how to render data in a pleaseant way, not what data to render.
You can make use of zip(…)
[python-doc] to generate 2-tuples of items, and then enumerate over these 2-tuples in the template:
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)
and then render this with:
{% 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 %}
the basket it is stored as a cookie.
I would advise not to work with cookies. Cookies can easily be manipulated by the user through request forgery. This thus means that a user can alter the cookies and for example make an order with
[{"id":"2","quantity":"-10"},{"id":"3","quantity":"5"},{"id":"5","quantity":"3"}]
so a person can order a negative amount of pizzas to reduce the price. The user has the freedom to submit a different structure and try to look for vulnerabilities. If you want to have data that is attached to the session, it is better to make use of session variables [Django-doc], since these are stored at the server side.
Upvotes: 2