I am tracking the total cost of items in a shopping cart with Django. My problem is the first item is tracked. When you deduct quantity or reduce quantity the price adjust. But anything that is below it does NOT adjust the total cost. I think the problem is I am not looping through it incorrectly so after many hours of failure I figured I would ask.
In
def cart()
I am looping through the member variables add updating
their values. The problem I am facing is that only the book_id is being passed to the cart() function when you click remove_from_cart
But if it was a problem of only one book_id being passed in then how come only the first item in the cart list is being changed regardless of the book_id that is being passed in?
views.py
#login_required
def add_to_cart(request,book_id):
book = get_object_or_404(Book, pk=book_id)
cart,created = Cart.objects.get_or_create(user=request.user, active=True)
order,created = BookOrder.objects.get_or_create(book=book,cart=cart)
order.quantity += 1
order.save()
messages.success(request, "Cart updated!")
return redirect('cart')
def remove_from_cart(request, book_id):
if request.user.is_authenticated():
try:
book = Book.objects.get(pk = book_id)
except ObjectDoesNotExist:
pass
else:
cart = Cart.objects.get(user = request.user, active = True)
cart.remove_from_cart(book_id)
return redirect('cart')
else:
return redirect('index')
def cart(request):
if request.user.is_authenticated():
cart = Cart.objects.filter(user=request.user.id, active = True)
orders = BookOrder.objects.filter(cart=cart)
total = 0
count = 0
for order in orders:
total += order.book.price * order.quantity
count += order.quantity
context = {
'cart': orders,
'total': total,
'count': count,
}
return render(request, 'store/cart.html', context)
else:
return redirect('index')
Your indentation is slightly off
def cart(request):
if request.user.is_authenticated():
cart = Cart.objects.filter(user=request.user.id, active = True)
orders = BookOrder.objects.filter(cart=cart)
total = 0
count = 0
for order in orders:
total += order.book.price * order.quantity
count += order.quantity
#Indentation needs to be offset by one level from here on
context = {
'cart': orders,
'total': total,
'count': count,
}
return render(request, 'store/cart.html', context)
else:
return redirect('index')
Related
I want to add all the amount field during a date range query search. I have an Income Model with date and amount fields among others. And any time a user select between two dates, I want the amount fields of the query results added as total.
Here is what I have tried:
def SearchIncomeRange(request):
listIncome = Income.objects.all()
searchForm = IncomeSearchForm(request.POST or None)
if request.method == 'POST':
listIncome = Income.objects.filter(
description__icontains=searchForm['description'].value(),
date__range=[
searchForm['start_date'].value(),
searchForm['end_date'].value()
]
)
else:
searchForm = IncomeSearchForm()
paginator = Paginator(listIncome, 5)
page = request.GET.get('page')
paged_income = paginator.get_page(page)
context = {
'searchForm':searchForm,
}
return render(request, 'cashier/search_income_range.html', context)
I am able to get the correct search result but getting the total I don't know how to use the SUM in the above query and pass the total in pagination. So Someone should please help me out. Thanks
from django.db.models import Sum
total_amount = listIncome.aggregate(total=Sum('amount'))
where listIncome is your queryset
Edit:
You should pass queryset in pagination with filtered queryset if any filter you apply.
I changed your written code but you can write this code in a good way.
def SearchIncomeRange(request):
listIncome = Income.objects.all()
searchForm = IncomeSearchForm(request.POST or None)
if request.method == 'POST':
# you can get filter value by your form data
post_data = request.POST
description = post_data['description']
start_date = post_data['start_date']
end_date = post_data['end_date']
else:
# you can get filter value by your query params
query_params = request.GET
description = query_params.get('description')
start_date = query_params.get('start_date')
end_date = query_params.get('end_date')
# Apply filter before pagination
listIncome = listIncome.filter(
description__icontains=description,
date__range=[start_date, end_date]
)
# calculate total_amount
total_amount = listIncome.aggregate(total=Sum('amount'))
paginator = Paginator(listIncome, 5)
page = request.GET.get('page')
paged_income = paginator.get_page(page)
# you can access total_amount in template by passing in context data
context = {
'searchForm':searchForm,
'total_amount': total_amount
}
return render(request, 'cashier/search_income_range.html', context)
Can anyone please help me to fix this problem local variable 'intent' referenced before assignment i could not find out why client_secret in the context is triggered. to my knowledge if the code in if statement fails then else block will be executed but i have set a print statement and it does not appear in the teminal either. if someone can please help me in solving this issue.
from django.shortcuts import render, redirect, reverse
from django.contrib import messages
from django.conf import settings
from .forms import OrderForm
from .models import Order, OrderLineItem, ProductLineItem, ExerciseLineItem, NutritionLineItem
from merchandise.models import Product
from exercise.models import ExercisePlans
from nutrition.models import NutritionPlans
from cart.contexts import cart_contents
import stripe
def checkout(request):
stripe_public_key = settings.STRIPE_PUBLIC_KEY
stripe_secret_key = settings.STRIPE_SECRET_KEY
if request.method == 'POST':
cart = request.session.get('cart', {
'merchandise_dic': {},
'excercise_plans_dic': {},
'nutrition_plans_dic': {},
})
form_data = {
'full_name': request.POST['full_name'],
'email': request.POST['email'],
'phone_number': request.POST['phone_number'],
'country': request.POST['country'],
'postcode': request.POST['postcode'],
'town_or_city': request.POST['town_or_city'],
'street_address1': request.POST['street_address1'],
'street_address2': request.POST['street_address2'],
'county': request.POST['county'],
}
order_form = OrderForm(form_data)
if order_form.is_valid():
print("Order form is valid")
order = order_form.save()
for product_type, dic in cart.items():
if product_type == 'merchandise_dic':
for item_id, quantity in dic.items():
print(f"This is item id of merchandise: {item_id}")
print(f"This is quantity of merchandise: {quantity}")
product = Product.objects.get(id=item_id)
print(product)
order_line_item = ProductLineItem(
order=order,
product=product,
quantity=quantity,
)
order_line_item.save()
elif product_type == 'excercise_plans_dic':
for item_id, quantity in dic.items():
print(f"This is item id of exercise plan: {item_id}")
print(f"This is quantity of exercise plan: {quantity}")
product = ExercisePlans.objects.get(id=item_id)
print(product)
order_line_item = ExerciseLineItem(
order=order,
product=product,
quantity=quantity,
)
order_line_item.save()
elif product_type == 'nutrition_plans_dic':
for item_id, quantity in dic.items():
print(f"This is item id of nutrition plan: {item_id}")
print(f"This is quantity of nutrition plan: {quantity}")
product = NutritionPlans.objects.get(id=item_id)
print(product)
order_line_item = NutritionLineItem(
order=order,
product=product,
quantity=quantity,
)
order_line_item.save()
else:
print("Order form is invalid")
messages.error(request, ('There was an error with your form. '
'Please double check your information.'))
return redirect(reverse('checkout'))
else:
print("Order form is invalid")
cart = request.session.get('cart', {
'merchandise_dic': {},
'excercise_plans_dic': {},
'nutrition_plans_dic': {},
})
if not cart:
messages.error(request,
"There is nothing in your \
shopping cart at the moment")
return redirect(reverse('products'))
""" Got total from cart_contents """
current_cart = cart_contents(request)
current_total = current_cart['total']
stripe_total = round(current_total * 100)
""" Set secret key on stripe """
stripe.api_key = stripe_secret_key
""" Created payment intent """
intent = stripe.PaymentIntent.create(
amount=stripe_total,
currency=settings.STRIPE_CURRENCY,
)
print(intent)
order_form = OrderForm()
if not stripe_public_key:
messages.warning(request, 'Stripe public key is missing. \
Did you forget to set it in your environment?')
template = 'checkout/checkout.html'
context = {
'order_form': order_form,
'stripe_public_key': stripe_public_key,
'client_secret': intent.client_secret,
}
return render(request, template, context)
If your method == "POST": is true then the intent variable is not assigned any parameter.
context = {
'order_form': order_form,
'stripe_public_key': stripe_public_key,
'client_secret': intent.client_secret,
}
Hence, the intent in last section is not assigned anything.
else:
print("Order form is invalid")
cart = request.session.get('cart', {
'merchandise_dic': {},
'excercise_plans_dic': {},
'nutrition_plans_dic': {},
})
if not cart:
messages.error(request,
"There is nothing in your \
shopping cart at the moment")
return redirect(reverse('products'))
""" Got total from cart_contents """
current_cart = cart_contents(request)
current_total = current_cart['total']
stripe_total = round(current_total * 100)
""" Set secret key on stripe """
stripe.api_key = stripe_secret_key
""" Created payment intent """
---> intent = stripe.PaymentIntent.create(
amount=stripe_total,
currency=settings.STRIPE_CURRENCY,
)
print(intent)
order_form = OrderForm()
intent is assigned inside the else block, but it is referenced outside the else block
context = {
'order_form': order_form,
'stripe_public_key': stripe_public_key,
---> 'client_secret': intent.client_secret,
So if the else block is not executed there is no intent variable.
Thanks every one for your valuable input I found the problem and fixed it. Actually I was not returning anything if the form is valid! Thus I was missing the redirect to checkout_success page at the first for loop level before 1st else.
That is why even if the form is valid it's still trying to return the render() statement at the bottom which was causing this error. Thus I created a checkout_success view and and also checkout_success.html and redirected to it. like this and fixed this error.
return redirect(reverse('checkout_success',
args=[order.order_number]))
def Cart(request):
if request.user.is_authenticated:
customer=request.user.customer
order,created=Order.objects.get_or_create(customer=customer,complete=True)
items=order.orderitem_set.all()
print(items)
else:
items=[]
context={"items":items}
return render(request,'store/Cart.html',context)
i'm trying to show some orderitems in the Cart template but nothing appears so i tried to
print the items and i get a an despite in the admin pannel i assisgned in an order some orderitems
try this
def Cart(request):
if request.user.is_authenticated:
customer=request.user.customer
order=Order.objects.get_or_create(customer__user=customer,complete=True)
items=order.orderitem_set.all()
print(items)
else:
items=[]
context={"items":items}
return render(request,'store/Cart.html',context)
I am trying to increment my DB by 1 if a user has not visited that unique item.pk before. At the moment it will only increment by 1 for all items in my DB, id like to to increment by 1 for each item.pk in the DB.
The view is to Create a view that returns a single bug object based on the bug ID (pk) and render it to the bug_detail.html template or return 404 error if object is not found Also handles commenting on the bug as well as regulating the amount of views attributed to the bug.
def bug_detail(request, pk):
bug = get_object_or_404(Bug, pk=pk)
if request.method == "POST":
form = BugCommentForm(request.POST)
if form.is_valid():
bugComment = form.save(commit=False)
bugComment.bug = bug
bugComment.author = request.user
bug.comment_number += 1
bug.save()
bugComment.save()
return redirect(reverse('bug_detail', kwargs={'pk': pk}))
else:
messages.error(
request,
"Looks like your comment is empty!",
extra_tags="alert-danger")
form = BugCommentForm(instance=bug)
return redirect(reverse('bug_detail', kwargs={'pk': pk}))
else:
form = BugCommentForm()
comments = BugComment.objects.filter(bug__pk=bug.pk)
comments_total = len(comments)
response = render(request,
'bug_detail.html',
{'bug': bug,
'comments': comments,
'comments_total': comments_total,
'form': form})
if 'last_visit' in request.COOKIES and 'bugg' in request.COOKIES:
last_visit = request.COOKIES['last_visit']
# the cookie is a string - convert back to a datetime type
last_visit_time = datetime.strptime(
last_visit[:-7], "%Y-%m-%d %H:%M:%S")
curr_time = datetime.now()
if (curr_time - last_visit_time).days > 0:
# if at least one day has gone by then inc the views count.
response.set_cookie('last_visit', datetime.now())
bug.views += 1
bug.save()
elif 'bugg' not in request.COOKIES:
response.set_cookie('last_visit', datetime.now())
response.set_cookie('bugg', bug.pk)
bug.views += 1
bug.save()
else:
response.set_cookie('last_visit', datetime.now())
response.set_cookie('bugg', bug.pk)
bug.views += 1
bug.save()
return response
I have a Django program that was developed in Notepad++ but now I have installed Pydev for Eclipse, so , I want to develop the program in Eclipse going forward.
I have cart.py and views.py module under the cart folder but when I import the cart module in views.py file, I get a error--Unresolved import:cart ---on the views.py file import statement..Any help would be appreciated.
cart.py
from cart.models import CartItem
from catalog.models import Product
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect
import decimal
import random
CART_ID_SESSION_KEY = 'cart_id'
#get the current users cart id,set new one if blank
def _cart_id(request):
print 'Get Cart Id'
if request.session.get(CART_ID_SESSION_KEY,'') == '':
print 'Failing here start'
request.session[CART_ID_SESSION_KEY] = _generate_cart_id()
print 'Failing here End'
return request.session[CART_ID_SESSION_KEY]
#
def _generate_cart_id():
print 'Generate cart id'
cart_id = ''
characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!##$%^&*()'
cart_id_length = 50
for y in range(cart_id_length):
cart_id += characters[random.randint(0,len(characters)-1)]
return cart_id
#return all items form the current users cart
def get_cart_items(request):
return CartItem.objects.filter(cart_id =_cart_id(request))
#add an item to the cart
def add_to_cart(request):
postdata = request.POST.copy()
#get product slug from post.data, return blank if empty
product_slug = postdata.get('product_slug','')
#get quantity added,return 1 if empty
quantity = postdata.get('quantity',1)
#fetch the product or return a missing page error
p = get_object_or_404(Product, slug=product_slug)
#get producsts in cart
cart_products = get_cart_items(request)
#check to see if the item is already in cart
product_in_cart = False
for cart_item in cart_products:
if cart_item.product.id == p.id:
cart_item.augment_quantity(quantity)
product_in_cart = True
if not product_in_cart:
ci = CartItem()
ci.product = p
ci.quantity = quantity
ci.cart_id = _cart_id(request)
ci.save()
def cart_distinct_item_count(request):
return get_cart_items(request).count()
views.py
import decimal
from django.shortcuts import render_to_response
from django.template import RequestContext
from ..cart import cart
from django.shortcuts import get_object_or_404
def show_cart(request, template_name="cart/cart.html"):
if request.method == 'POST':
postdata = request.POST.copy()
if postdata['submit'] == 'Remove':
cart.remove_from_cart(request)
if postdata['submit'] == 'Update':
cart.update_cart(request)
cart_items = cart.get_cart_items(request)
page_title = 'Shopping Cart'
cart_subtotal = cart.cart_subtotal(request)
return render_to_response(template_name, locals(),
context_instance=RequestContext(request))
def get_single_item(request, item_id):
return get_object_or_404(CartItem, id=item_id, cart_id=_cart_id(request))
# update quantity for single item
def update_cart(request):
postdata = request.POST.copy()
item_id = postdata['item_id']
quantity = postdata['quantity']
cart_item = get_single_item(request, item_id)
if cart_item:
if int(quantity) > 0:
cart_item.quantity = int(quantity)
cart_item.save()
else:
remove_from_cart(request)
# remove a single item from cart
def remove_from_cart(request):
postdata = request.POST.copy()
item_id = postdata['item_id']
cart_item = get_single_item(request, item_id)
if cart_item:
cart_item.delete()
# gets the total cost for the current cart
def cart_subtotal(request):
cart_total = decimal.Decimal('0.00')
cart_products = get_cart_items(request)
for cart_item in cart_products:
cart_total += cart_item.product.price * cart_item.quantity
return cart_total
The .. in front of from ..cart import cart is probably messing with you.
This means cart.py should be one level up directory-wise than views.py, which from your question derived - is not the case.