I have a views.py and contexts.py that adds a product with a particular flavour to the basket on my Django site. I have copied this logic from a course I'm on. I now want to be able to have multiple variations on products and add them to my basket. For instance a strength as well as a flavour. Here is my add_product view:
def add_to_basket(request, item_id):
""" Add a quantity of the specified product to the shopping basket """
product = get_object_or_404(Product, pk=item_id)
quantity = int(request.POST.get('quantity'))
redirect_url = request.POST.get('redirect_url')
flavour = None
if 'product_flavour' in request.POST:
flavour = request.POST['product_flavour']
strength = None
if 'product_strength' in request.POST:
strength = request.POST['product_strength']
basket = request.session.get('basket', {})
if flavour:
if item_id in list(basket.keys()):
if flavour in basket[item_id]['items_by_flavour'].keys():
basket[item_id]['items_by_flavour'][flavour] += quantity
messages.success(request, f'Updated {product.name} flavour {flavour.upper()} quantity to {basket[item_id]["items_by_flavour"][flavour]}')
else:
basket[item_id]['items_by_flavour'][flavour] = quantity
messages.success(request, f'Added {product.name} flavour {flavour.upper()} to your basket')
else:
basket[item_id] = {'items_by_flavour': {flavour: quantity}}
messages.success(request, f'Added {product.name} flavour {flavour.upper()} to your basket')
else:
if item_id in list(basket.keys()):
basket[item_id] += quantity
messages.success(request, f'Updated {product.name} quantity to {basket[item_id]}')
else:
basket[item_id] = quantity
messages.success(request, f'Added {product.name} to your basket')
request.session['basket'] = basket
return redirect(redirect_url)
Here is my contexts.py that gets back the contents of the basket:
def basket_contents(request):
basket_items = []
total = 0
product_count = 0
basket = request.session.get('basket', {})
for item_id, item_data in basket.items():
if isinstance(item_data, int):
product = get_object_or_404(Product, pk=item_id)
total += item_data * product.price
product_count += item_data
basket_items.append({
'item_id': item_id,
'quantity': item_data,
'product': product,
})
else:
product = get_object_or_404(Product, pk=item_id)
for flavour, quantity in item_data['items_by_flavour'].items():
total += quantity * product.price
product_count += quantity
basket_items.append({
'item_id': item_id,
'quantity': quantity,
'product': product,
'flavour': flavour,
})
if total < settings.FREE_DELIVERY_THRESHOLD:
delivery = total * Decimal(settings.STANDARD_DELIVERY_PERCENTAGE / 100)
free_delivery_delta = settings.FREE_DELIVERY_THRESHOLD - total
else:
delivery = 0
free_delivery_delta = 0
grand_total = delivery + total
context = {
'basket_items': basket_items,
'total': total,
'product_count': product_count,
'delivery': delivery,
'free_delivery_delta': free_delivery_delta,
'free_delivery_threshold': settings.FREE_DELIVERY_THRESHOLD,
'grand_total': grand_total,
}
return context
Essentially what the view does is check whether the product already exists in the basket with that flavour, if it does it increases the quantity of that product in the basket by the number the user selects. If the product doesn't exist with that flavour in the basket then it adds it to the basket with quantity selected. If the product doesn't have a flavour then it adds that product to the basket without a flavour. I want to keep this same logic but be able to have more variations. So for instance if the basket already has a product with a flavour and strength then it will increase the quantity of that flavour and strength. If the the basket doesn't have a product with that flavour and strength then it will add it to the basket with the quantity selected. If it doesn't have a flavour or strength then it will add it to the basket.