I am creating a shopping cart with the code below
`
SESSION_COOKIE_AGE=300
SESSION_EXPIRE_AT_BROWSER_CLOSE =True
#require_POST
def cart_add(request, product_id):
product = get_object_or_404(Product, id=product_id)
quantity = request.POST.get('quantity')
product_id =str(product.id)
request.session[product_id] ={"product_name":str(product.title),"price":str(product.price),"quantity":quantity}
items =request.session.items()
print(items)
return render(request, 'cart/display_cart.html', {"products":request.session})`
Scenario one
when I pass items to my view like this=> return render(request, 'cart/display_cart.html', {"products":items}) and loop over it in the template using {% for item in products %}{{ item.product_name }} {% endfor %} nothing shows. but when I print it=> print(items) I get dict_items([('7', {'product_name': 'Tomatoe', 'price': '15.00', 'quantity': '3'})]) in my console. how can i print the items in my template
Scenario 2
when I pass request.session like this => return render(request, 'cart/display_cart.html', {"products":request.session}) and I do
{% for key, value in products.items %}
<li>{{value}}</li>
{% endfor %}
in my template I get
{'product_name': 'Tomatoe', 'price': '20.00', 'quantity': '1'}. how can I display the items in my template using product_name instead of key? Thank you
items is a nested dict
Use:
{% for k, item in products.items %}
{{ item.product_name }}
{% endfor %}
Related
I've five Product objects with 3 product's availability set to True and rest False, I'm trying to set Checkout Status Button to Out of Stock even if one product has availablity set to False.
Because cart view cannot use slug, {% if product.availability %} is pointless, and can't use 'for loop' or it would create multiple checkout buttons, what's the way to fix this?
Model
class Product(models.Model):
availablity = models.BooleanField()
View
def cart(request):
products = Product.objects.all()
Cart template
{% for product in products %}
<p>{product.name}</p>
<p>{product.price}</p>
{% endfor %}
<!--Checkout Status Button-->
{% if product.availability %}
Checkout
{% else %}
<p>Out of stock</p>
{% endif %}
You should do all calculation in view and send only single True/False to template.
For example
products = Product.objects.all()
available = all(x.availability for x in products)
context = {..., "available": available}
{% if available %}
Checkout
{% else %}
<p>Out of stock</p>
{% endif %}
def cart(request):
products = Product.objects.all()
availibility = True
for prod in products:
if prod.availability = False:
availability = False
break
context = { "products" :products, "availability" :availability }
in Html
if availability` True then show `Checkout` else `Out of Stock`
In your cart view, you could add a context dictionary to your render() call?
So basically :
Check products for the availability condition and set a variable available to True/False
change your render call to render(cart_template, {'products' : products, 'available' : available})
change your cart template to use {% if available %}
My template receives from views.py following nested dictionary of shopping cart content.
{
'20':
{'userid': 1,
'product_id': 20,
'name': 'Venus de Milos',
'quantity': 1,
'price': '1500.00',
'image': '/media/static/photos/pngegg.png'},
'23':
{'userid': 1,
'product_id': 23,
'name': 'Bicycle',
'quantity': 1,
'price': '1000.00',
'image': '/media/static/photos/366f.png'}
}
I am having problem with iteration through it.
For example, when I am using following code,
{% for key, value in list %}
{{ key }} {{ value }}
{% endfor %}
instead of keys and values I receive just this:
2 0
2 3
My goal is to calculate grand total through multiplying quantity and price for each product and dding it all together with each product in cart.
May sombody give me a hand on this, or at least help to figure out how to iterate properly through nested dictionary?
i am using following lib for cart:
https://pypi.org/project/django-shopping-cart/
views.py:
#login_required(login_url="/users/login")
def cart_detail(request):
cart = Cart(request)
queryset = cart.cart
context = {"list": queryset }
return render(request, 'cart_detail.html', context)
SOLVED (kind of):
Following your advice, I've wrote calculation for "total" in views.py
BUT, since dictionary of product has 6 attributes, "total" is added 6 times in loop, for each product in cart.
For now I've just added division by 6, but obviously this is not rational solution
def cart_detail(request):
cart = Cart(request)
queryset = cart.cart
total_price=0
for key, value in queryset.items():
for key1, value1 in value.items():
total_price = total_price + (float(value['quantity']) * float(value['price']))
#Temporal decision
total_price = total_price / 6
context = {"list": queryset, "total_price": total_price }
return render(request, 'cart_detail.html', context)
you can try like this:
{% for key, value in list.items %} <-first loop
{{ key }}
{% for key1, value1 in value.items %} <-- second loop
{{ key1 }} - {{ value1 }}
{% endfor %}
{% endfor %}
{{ key }} will give you the key of outer dict, in your case 20 and 23
{{ key1 }} will give you the key of nested dict user_id, name,...
{{ value1 }} will give you the value of nested dict.
Hope it can help
I suggest you to do the calculations in views.py, save them into variables and then pass it to template.
Assuming that your
is saved in the variable cart_dict:
total_price=0
for product in cart_dict:
total_price = total_price + (float(product['quantity']) * float(product['price']))
context = {"cart_dict: cart_dict, "total_price": total_price }
return render(request, 'cart_detail.html', context)
This loop format in html is only printing the key but not value,I want to print both key and value in html page.
views.py
def predict(request):
if request.method == "POST":
dict = {'Name': John, 'Age': 40}
return render(request,'standalone.html',{'content':dict})
else:
return render(request,'test_homepage.html')
satandalone.html
{% for c in content %}
{{c}}
{% endfor %}
You use .items() to obtain an iterable of 2-tuples.
def predict(request):
if request.method == "POST":
data = {'Name': 'John', 'Age': 40}
return render(request,'standalone.html',{'content': data.items()})
else:
return render(request,'test_homepage.html')
In the template, you can then render this with:
{% for k, v in content %}
{{ k }}: {{ v }}
{% endfor %}
Note: Please do not name a variable dict, it overrides the reference to the dict
class. Use for example data.
Try this in your template satandalone.html:
{% for c in content %}
{{ c.name }}
{{ c.age }}
{% endfor %}
Try this. It might help you.
{% for key, value in content.items %}
{{ key }}: {{ value }}
{% endfor %}
I am using Django to render a menu of items. I can get the content I want just fine, but when I return it to the django template, it's just a json string so it won't iterate correct. How do I tell django to return it as an iterable object?
I ran across this article. Maybe I want to merge query sets?
Python
def index(request):
if not request.user.is_authenticated:
return redirect('/login', {'message': None})
try:
menu_categories = MenuCategory.objects.all()
menu = []
for cat in menu_categories:
items = MenuCategoryItems.objects.filter(category_id=cat.id).all()
menu.append({'category': cat, 'items': items})
context = {'menu': menu}
# for cat in menu_categories:
# items = menu_items.filter(category_id=cat.id)
# category_items = []
# for item in items:
# category_items.append({
# "name": item.name,
# "price": float(item.price),
# "id": item.id
# })
# menu.append({"category": cat.name, "items": category_items})
except Exception:
print('failure')
return render(request, 'index.html', context)
Template
{% for category in menu %}
<div>{{ category.name }}</div>
{# {% for item in category.items %}#}
{# <div>{{ item.name }} | {{ item.price }}</div>#}
{# {% endfor %}#}
{% endfor %}
I think I have found my answer. This worked for me but I'm not sure if it's the 'preferred' way.
Python
def index(request):
if not request.user.is_authenticated:
return redirect('/login', {'message': None})
try:
menu_categories = MenuCategory.objects.all()
menu = []
for cat in menu_categories:
items = MenuCategoryItems.objects.filter(category_id=cat.id).all()
menu.append({'category': cat, 'items': items.values})
context = {'menu': menu}
except Exception:
print('failure')
return render(request, 'index.html', context)
Template
{% for category in menu %}
<div><strong>{{ category.category.name }}</strong></div>
{% for item in category.items %}
<div>{{ item.name }} - {{ item.price }}</div>
{% endfor %}
{% endfor %}
How could I take the below collection and iterate over it in a
django template ?
[('Foo Key', [{'lname': 'Bar', 'fname': 'Foo'}])]
Please note the above example is much smaller just to keep things simple.
If we need the fully expanded collection, e.g if size matters, I can update this post.
My closest successful attempt is noted below.
{% for key0, value0 in data %}
<tr>
<td> key0 {{ key0 }}:</td>
<td> value0 {{ value0 }} </td>
</tr>
<p> {% for value1 in value0 %}
<td> {{ value1 }}</td>
{% endfor %}
</p>
{% endfor %}
and this will leave me with the below output.
Foo Key {'lname': 'Bar', 'fname': 'Foo'}
I cannot seem to get 'Bar' or 'Foo' out of it.
Some other context
Here is the view where the data is produced
from django.shortcuts import render
from .models import Person, PersonMeta
# Create your views here.
def thanks(request):
return render(request, 'thanks.html')
from .forms import NameForm
def home(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
data = {}
# process the data in form.cleaned_data as required
currentUser = request.user
person = Person.objects.create(first_name=currentUser.first_name, last_name=currentUser.last_name,
nickname=form.cleaned_data['nickname'])
# getting front loaded personMeta
personDetails = PersonMeta.objects.filter(frontLoaded_first_name=currentUser.first_name,frontLoaded_last_name=currentUser.last_name).values()
# setting key
currUserKey = "{0} {1}".format(currentUser.first_name, currentUser.last_name)
# if person details is not false
# this if may not have to be here.
if (personDetails):
data[currUserKey] = personDetails
# redirect to a new URL:
return render(request, 'signUp.html', {'data': sorted(data.items())})
# if a GET (or any other method) we'll create a blank form
#
else:
form = NameForm()
return render(request, 'home.html', {'form': form})
You have a dict inside a list which is the second value of a tuple inside another list:
[('Foo Key', [{'lname': 'Bar', 'fname': 'Foo'}])]
So here we go:
{% for tuple in data %}
<p>Tuple key: {{ tuple.0 }}</p>
{% for key, value in tuple.1.0.items %}
<p>Dict key, value: {{ key }}: {{ value }}</p>
{% endfor %}
{% endfor %}