I am following the shopping cart example from django ecommerce book and I am facing an issue when it comes to remove items from shopping cart, I cannot get to remove single items from the session.
This is part of my cart.py
class Cart(object):
class Item(object):
def __init__(self, itemid, product, quantity=1, price=0):
self.itemid = itemid
self.product = product
self.quantity = quantity
self.price = price
self.totalprice = price * quantity
def remove_item(self, itemid):
self.items = filter(lambda x: x.itemid != itemid, self.items)
views.py
def remove_from_cart(request, cart_item_id):
cart = get_shopping_cart(request)
cart.remove_item(int(cart_item_id))
update_shopping_cart(request, cart)
cart = get_shopping_cart(request)
ctx = {'cart': cart}
I am using Python 2.7 and Django 1.5. Is anything wrong with the definition of the remove_item method? I have tried several options but coudn't make it work
Any hint would be appreciated.
EDIT: my update_shopping_cart method is:
def update_shopping_cart(request, cart):
request.session['cart'] = cart
The view where the cart allows remove items:
def shopping_cart(request):
cart = get_shopping_cart(request)
if request.method == 'POST':
cart = get_shopping_cart(request)
cart.remove_item(cart_item_id)
update_shopping_cart(request, cart)
cart = get_shopping_cart(request)
ctx = {'cart': cart}
render_to_response(...)
I think there are two issues:
Did you set SESSION_SAVE_EVERY_REQUEST=True?
In the method
def remove_from_cart(request, cart_item_id):
cart = get_shopping_cart(request)
cart.remove_item(int(cart_item_id))
update_shopping_cart(request, cart)
cart = get_shopping_cart(request)
ctx = {'cart': cart}
you are actually fetching your data, then changing it to then fetch again the old data. Why do you do the second cart = get_shopping_cart(request)? That probably overwrites the changes you have just made.
Adapt the code as follows
def remove_from_cart(request, cart_item_id):
cart = get_shopping_cart(request)
cart.remove_item(int(cart_item_id))
update_shopping_cart(request, cart)
# cart = get_shopping_cart(request)
ctx = {'cart': cart}
and adapt your update_shopping_cart(request, cart) as Greg suggests to
def update_shopping_cart(request, cart):
request.session['cart'] = cart
request.session.modified = True
Does adding this line help?
def update_shopping_cart(request, cart):
request.session['cart'] = cart
request.session.modified = True
Related
Hi Everyone,
I am new to python and django and creating a fitness website. I have three apps, one is for the products, one for exercise plans and one for nutrition plans. I am able to add the products in the shopping cart. But wonder how can i do this for the exercise plan app and nutrition plan app. Can any one please suggest a simple way out please. The logic that i have at the moment i can add products from the merchandise app but can any one tell please how i can restructure the logic so that i would be able to add products from exercise
here is add to cart:
def add_cart(request, item_id):
""" Add quantity of specified product to the shopping cart """
quantity = int(request.POST.get('quantity'))
redirect_url = request.POST.get('redirect_url')
cart = request.session.get('cart', {})
if item_id in list(cart.keys()):
cart[item_id] += quantity
else:
cart[item_id] = quantity
request.session['cart'] = cart
return redirect(redirect_url)
Here is my contexts.py
from django.shortcuts import get_object_or_404
from merchandise.models import Product
def cart_contents(request):
cart_items = []
total = 0
product_count = 0
cart = request.session.get('cart', {})
for item_id, quantity in cart.items():
product = get_object_or_404(Product, pk=item_id)
total += quantity * product.price
product_count += quantity
cart_items.append({
'item_id': item_id,
'quantity': quantity,
'product': product,
})
context = {
'cart_items': cart_items,
'total': total,
'product_count': product_count
}
return context
I am building online store and want to use sessions to allow anonymous users to add items to carts before logging in .
trying to save the added items in session as a list but it saves only last object added to list
def cart(request):
user_id = request.user.id
cart_items =Cart.objects.all().filter(user_id=user_id, is_ordered=False)
ids = request.session.get('cart_id')
if ids:
for cart_id in ids:
if request.user.is_authenticated:
cart = Cart.objects.get(id=cart_id)
if cart:
cart.user = request.user
cart.save()
# get total prices
prices = []
for item in cart_items:
prices.append(item.item.price * item.qty)
total_price = sum(prices)
context = {
'items': cart_items,
'total_price': total_price
}
request.session['prices'] = prices
return render(request, 'cart.html', context)
def add_to_cart(request):
if request.user.is_authenticated:
item = Item.objects.get(pk=request.POST['item_id'])
cart = Cart.objects.filter(
user=request.user, item=item, is_ordered=False).first()
if cart:
cart.qty += 1
cart.save()
messages.success(request, 'item added to cart!')
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
else:
cart = Cart(user=request.user, item=item)
cart.save()
messages.success(request, 'item added to cart!')
else:
carts_ids = []
session_cart = request.session.get('cart_id')
item = Item.objects.get(pk=request.POST['item_id'])
if session_cart :
for cart in session_cart:
carts = Cart.objects.all().filter(id=cart, item=item)
if carts:
cart = carts.filter(item=item)[0]
print(cart.qty)
cart.qty += 1
cart.save()
else:
print('new cart')
new_cart = Cart(item=item)
new_cart.save()
carts_ids.append(new_cart.id)
request.session['cart_id'] = carts_ids
else:
print('new session')
new_cart = Cart(item=item)
new_cart.save()
carts_ids.append(new_cart.id)
request.session['cart_id'] = carts_ids
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
here are my models.py
and the full code on github i am only working now on these to views (cart and add_to_cart)
appriciate any help to get over this and to simplify my code :)
The idea would be that you save the whole cart in sessions so that you can reload it when the same user comes back to your website. So your code should look like this:
prices = []
itemlist=[]
for item in cart_items:
prices.append(item.item.price * item.qty)
itemlist.append(item.item, item.qty)
total_price = sum(prices)
context = {
'items': cart_items,
'total_price': total_price
}
request.session['items'] = itemlist
End then you also will need to read out this list.
this code is from djagno 2 by example book
which is very helpful by the way. the question here is how we managed to modify the request session although we didn't modify it except in save method ((( and it's on the session of the cart which in the first line after init)))
what i see is that we have made a copy from the session dictionary at this line
self.session = request.session
class Cart(object):
def __init__(self, request):
self.session = request.session
cart = self.session.get(settings.CART_SESSION_ID)
if not cart:
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
def add(self, product, quantity=1, update_quantity=False):
'''
Add a product to the cart or update it is quantity
'''
product_id = product.id
if not product_id in self.cart:
self.cart[product_id] = {'quantity': 0,
'price': str(product.price)}
if update_quantity:
self.cart[product_id]['quantity'] = quantity
else:
self.cart[product_id]['quantity'] += quantity
self.save()
def save(self):
self.session['modified'] = True
for more clarification you can find the whole code of the project here
code
i managed to see the user session as I passed it from the context to the template and it's already modified
This line does not make a copy:
self.session = request.session
The session in the Cart instance is the request session. self.cart is a dictionary in that session, so all changes to it are written directly to the session. Then when save is called the modified flag is set.
I am adding items to m2m using add() method but after adding items, how can I know whether any new items added or not, for better understanding have a look at my code
def new_or_get(self, request):
user = request.user
cart_id = request.session.get("cart_id", None)
kart = get_or_none(Cart,id=cart_id)
if kart:
new_obj = False
cart_obj = kart
if user.is_authenticated and cart_obj.user is None:
try:
cart = self.get(user=user)
cart.products.add(*cart_obj.products.all())
cart.messages = 'A'
cart.save()
cart_obj.delete()
cart_obj = cart
except:
cart_obj.user = user
cart_obj.save()
else:
cart_obj = kart
what I want is cart.messages = 'A' will only execute when new items added to cart, is there any builtin method for this, if not then how can I do this.
Hello I am working on my ecommerce django tutorial and for some reason my simple cart count is not working. Everytime I add to the cart the {{cart_item_count}} in my cart.html is 0
Also in relation to this code the book has my carts.py as cart.py but since the app is cart for some reason is doesnt like this so I renames my cart.py "carts.py" and did this
from cart import carts as cart
Does Django not allow a py file the same name as the app???
To help with the code
carts.py has a function def cart_disinct_item_count(request) which returns the count which is called in my views.py to set the variable "cart_item_count " which is displayed in my cart.html page but currently no matter what my form has is returns 0.
I didnt post the entire project code but I think I got all the related information needed.
Thanks
cart.html
{% block content %}
<h1>Cart Page Here</h1>
Cart item count: {{cart_item_count }}
{% endblock %}
cart views.py
# Create your views here.
from django.shortcuts import render_to_response
from django.template import RequestContext
from cart import carts as cart
def show_cart(request, template_name="cart/cart.html"):
cart_item_count = cart.cart_disinct_item_count(request)
page_title = 'Shopping Cart'
return render_to_response("cart/cart.html", locals(),
context_instance = RequestContext(request))
cart item model
class CartItem(models.Model):
cart_id = models.CharField(max_length=50)
date_added = models.DateTimeField(auto_now_add = True)
quantity = models.IntegerField(default = 1)
product = models.ForeignKey('catalog.Product', unique = False)
class Meta:
app_label = ''
db_table = 'cart_items'
ordering = ['date_added']
def total(self):
return self.quantity * self.product.price
def name(self):
return self.product.name
def price(self):
return self.product.price
def get_absolute_url(self):
return self.product.get_absolute_url()
def augment_quantity(self, quantity):
""" called when a POST request comes in for a Product instance already in the shopping cart """
self.quantity = self.quantity + int(quantity)
self.save()
carts.py
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 products in cart
cart_products = get_cart_items(request)
product_in_cart = False
#check to see if item is already in cart
for cart_item in cart_products:
if cart_item.product.id == p.id:
#update the quantity if found
cart_item.augment_quantity(quantity)
product_in_cart = True
if not product_in_cart:
#create and save a new cart item
ci = CartItem()
ci.product = p
ci.quantity = quantity
ci.cart_id = _cart_id(request)
ci.save()
#returns the total number of items in the user's cart
def cart_disinct_item_count(request):
return get_cart_items(request).count()
forms.py:
class ProductAddToCartForm(forms.Form):
quantity = forms.IntegerField(widget=forms.TextInput(attrs={'size':'2',
'value':'1', 'class':'quantity'}),
error_messages={'invalid': 'Please enter a valid quantity'},
min_value = 1)
product_slug = forms.CharField(widget = forms.HiddenInput())
#override the default __init__ so we can set the request
def __init__(self, request = None, *args, **kwargs):
self.request = request
super(ProductAddToCartForm, self).__init__(*args, **kwargs)
*EDIT**
forgot to add the view that shows the product and calls add_to_cart:
#new product view, with POST vs GET detection
def show_product(request, product_slug, template_name = "catalog/product.html"):
p = get_object_or_404(Product, slug=product_slug)
categories = p.categories.all()
page_title = p.name
meta_keywords = p.meta_keywords
meta_description = p.meta_description
#need to evaluate the HTTP method
if request.method == 'POST':
#add to cart....create the bound form
postdata = request.POST.copy()
form = ProductAddToCartForm(request, postdata)
#check if posted data is valid
if form.is_valid():
#add to cart and redirect to cart page
cart.add_to_cart(request)
# if test cookie worked, get rid of it
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
url = urlresolvers.reverse('show_cart')
return HttpResponseRedirect(url)
else:
# it's a GET, create the unbound form. Note request as a kwarg
form = ProductAddToCartForm(request = request, label_suffix = ':')
#assign the hidden input the product slug
form.fields['product_slug'].widget.attrs['value'] = product_slug
#set the test cookie on our first GET request
request.session.set_test_cookie()
return render_to_response("catalog/product.html", locals(), context_instance=RequestContext(request))
Found the error :) Indentation issues (stupid python) j/k first one is mine and second one is the correct one. Gotta get use to this. Was easy to overlook to the untrained eye....
def add_to_cart(request):
postdata = request.POST.copy()
product_slug = postdata.get('product_slug', '')
quantity = postdata.get('quantity', 1)
p = get_object_or_404(Product, slug = product_slug)
cart_products = get_cart_items(request)
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()
Here is the books and it works:
def add_to_cart(request):
postdata = request.POST.copy()
product_slug = postdata.get('product_slug','')
quantity = postdata.get('quantity',1)
p = get_object_or_404(Product, slug=product_slug)
cart_products = get_cart_items(request)
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()