I am setting up a Django project to allow tickets to be sold for various theatre dates with a price for adults and a price for children. I have created a models.py and ticket_details.html.
I am unfortunately receiving the following error: 'int' object has no attribute 'get'
and I am at a loss to how I am to get the adult and child price for the total calculations to display in my bag.html.
The problem is with my contexts.py and views.py files. I have tried the 'get' option but it is not working. Can someone advise?
models.py:
class Show(models.Model):
'''Programmatic Name'''
name = models.CharField(max_length=254)
friendly_name = models.CharField(max_length=254, null=True, blank=True)
poster = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
def get_friendly_name(self):
return self.friendly_name
class Ticket(models.Model):
show = models.ForeignKey('show', null=True, blank=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=254)
event_date = models.CharField(max_length=254)
description = models.TextField(null=True, blank=True)
event_details = models.TextField(null=True, blank=True)
place = models.CharField(max_length=254)
location = models.CharField(max_length=254)
position = models.CharField(max_length=254)
image = models.ImageField(null=True, blank=True)
price_details = models.TextField(null=True, blank=True)
date = models.DateTimeField(null=True, blank=True)
adult_price = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
child_price = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
def __str__(self):
return self.name
ticket_detail.html:
<form action="{% url 'add_to_bag' ticket.id %}" method="POST">
{% csrf_token %}
<div >
<div >
<div >
<div >
<button data-item_id="{{ ticket.id }}"
id="decrement-qty_{{ ticket.id }}">
<span >
<i ></i>
</span>
</button>
</div>
<input type="number" name="adult_quantity" value="1" min="1"
max="99" data-item_id="{{ ticket.id }}" id="adult_ticket">
<div >
<button data-item_id="{{ ticket.id }}"
id="increment-qty_{{ ticket.id }}">
<span >
<i ></i>
</span>
</button>
</div>
</div>
<div >
<div >
<button data-item_id="{{ ticket.id }}"
id="decrement-qty_{{ ticket.id }}">
<span >
<i ></i>
</span>
</button>
</div>
<input type="number" name="child_quantity" value="1" min="1"
max="99" data-item_id="{{ ticket.id }}" id="child_ticket">
<div >
<button data-item_id="{{ ticket.id }}"
id="increment-qty_{{ ticket.id }}">
<span >
<i ></i>
</span>
</button>
</div>
</div>
</div>
<div >
<input type="submit"
value="Add to Bag" />
</div>
<input type="hidden" name="redirect_url" value="{{ request.path }}" />
</div>
</form>
I have created an app for 'bag' as well as a views.py and contexts.py accordingly.
bag.html
<div >
{% if bag_items %}
<div >
<table >
<tr>
<th scope="col">Ticket Info</th>
<th scope="col">Date</th>
<th scope="col">Price</th>
<th scope="col">Quantity</th>
<th scope="col">Sub Total</th>
</tr>
{% for item in bag_items %}
{% if item.adult_ticket %}
<tr>
<td>{{ item.ticket.name }}</td>
<td>{{ item.ticket.date}}</td>
<td>{{ item.ticket.adult_price }}</td>
<td>
<form method="POST" action="{% url 'adjust_bag' item.item_id %}">
{% csrf_token %}
<div >
<div >
<div >
<button
data-item_id="{{ item.item_id }}" id="decrement-qty_{{ item.item_id }}">
<span>
<i ></i>
</span>
</button>
</div>
<input type="number"
id="adult-ticket" name="adultquantity" value="{{ item.quantity }}" min="1"
max="99" data-item_id="{{ item.item_id }}" id="id_qty_{{ item.item_id }}">
<div >
<button
data-item_id="{{ item.item_id }}" id="increment-qty_{{ item.item_id }}">
<span>
<i ></i>
</span>
</button>
</div>
</div>
</div>
</form>
<a ><small>Update</small></a>
<a id="remove_{{ item.item_id }}"
data-product_size="{{ item.size }}"><small>Remove</small></a>
</td>
<td>${{ item.ticket.price|calc_subtotal:item.adult_quantity }}</td>
</tr>
{% elif item.child_ticket %}
<tr>
<td>{{ item.ticket.name }}</td>
<td>{{ item.ticket.date}}</td>
<td>{{ item.ticket.child_price }}</td>
<td>
<form method="POST" action="{% url 'adjust_bag' item.item_id %}">
{% csrf_token %}
<div >
<div >
<div >
<button
data-item_id="{{ item.item_id }}" id="decrement-qty_{{ item.item_id }}">
<span>
<i ></i>
</span>
</button>
</div>
<input type="number"
id="child-ticket" name="child_quantity" value="{{ item.quantity }}" min="1"
max="99" data-item_id="{{ item.item_id }}" id="id_qty_{{ item.item_id }}">
<div >
<button
data-item_id="{{ item.item_id }}" id="increment-qty_{{ item.item_id }}">
<span>
<i ></i>
</span>
</button>
</div>
</div>
</div>
</form>
<a ><small>Update</small></a>
<a id="remove_{{ item.item_id }}"
data-product_size="{{ item.size }}"><small>Remove</small></a>
</td>
<td>${{ item.ticket.price|calc_subtotal:item.child_quantity }}</td>
</tr>
{% endif %}
{% endfor %}
<tr>
<td>Bag Total: €{{ grand_total|floatformat:2 }}</td>
</tr>
</table>
</div>
{% else %}
<p>Your bag is empty</p>
{% endif %}
</div>
views.py
def add_to_bag(request, item_id):
'''Submit form to this view including ticket id and quanity'''
''' Add a quantity of the specified tickets to the shopping bag'''
child_quantity = int(request.POST.get('child_quantity'))
adult_quantity = int(request.POST.get('adult_quantity'))
redirect_url = request.POST.get('redirect_url')
bag = request.session.get('bag', {})
'''Once in view get bag variable if exisits in session or create if doesnt'''
'''Add to bag'''
def add_quantity(quantity, item_id, bag):
if quantity:
if item_id in list(bag.keys()):
bag[item_id] = quantity
else:
bag[item_id] = quantity
if adult_quantity or child_quantity:
if adult_quantity:
add_quantity(
adult_quantity,
'adult_quantity',
item_id,
bag,)
if child_quantity:
add_quantity(
child_quantity,
'child_quantity',
item_id,
bag,)
request.session['bag'] = bag
return redirect(redirect_url)
contexts.py
from django.conf import settings
from django.shortcuts import get_object_or_404
from tickets.models import Ticket
def bag_contents(request):
bag_items = []
'''Empty list for bag items to live in'''
total = 0
ticket_count = 0
bag = request.session.get('bag', {})
for item_id, adult_quantity in bag.items():
if adult_quantity.get('adult_quantity'):
ticket = get_object_or_404(Ticket, pk=item_id)
total = adult_quantity.get('adult_quantity') * ticket.adult_price
ticket_count = adult_quantity.get('adult_quantity')
bag_items.append({
'item_id': item_id,
'quantity': adult_quantity.get('adult_quantity'),
'ticket': ticket,
'adult_ticket': True,
})
for item_id, child_quantity in bag.items():
if child_quantity.get('child_quantity'):
ticket = get_object_or_404(Ticket, pk=item_id)
total = child_quantity.get('child_quantity') * ticket.child_price
ticket_count = child_quantity.get('child_quantity')
bag_items.append({
'item_id': item_id,
'quantity': child_quantity.get('child_quantity'),
'ticket': ticket,
'child_ticket': True,
})
grand_total = total
context = {
'bag_items': bag_items,
'total': total,
'ticket_count': ticket_count,
'grand_total': grand_total,
}
'''Make dictionary available to all templates across the enitire application'''
return context
CodePudding user response:
The issue is how you are iterating in for item_id, adult_quantity in bag.items():
. I see that bag
is a dictionary, and I think that it's a dictionary like:
{
'item_id': 1,
'quantity': 10,
'ticket': ticket,
'adult_ticket': True,
}
If this is correct, then why do you need to iterate through a bag
in contexts.py? Would this not work:
def bag_contents(request):
bag_items = []
'''Empty list for bag items to live in'''
total = 0
ticket_count = 0
bag = request.session.get('bag', {})
if 'item_id' in bag:
item_id = bag.item_id
else:
item_id = None
ticket = get_object_or_404(Ticket, pk=item_id)
if bag.adult_ticket:
total = bag.quantity * ticket.adult_price
bag_items.append({
'item_id': item_id,
'quantity': bag.quantity,
'ticket': ticket,
'adult_ticket': True,
})
if bag.child_ticket:
total = bag.quantity * ticket.child_price
bag_items.append({
'item_id': item_id,
'quantity': bag.quantity,
'ticket': ticket,
'child_ticket': True,
})
ticket_count = bag.quantity
grand_total = total
context = {
'bag_items': bag_items,
'total': total,
'ticket_count': ticket_count,
'grand_total': grand_total,
}
'''Make dictionary available to all templates across the enitire application'''
return context