Permalink
Browse files

chapter 5

  • Loading branch information...
1 parent 9c9efa9 commit 9662dac16da9cc31ca3b5405c210adc1e1251024 @ButuzGOL committed Apr 18, 2010
View
@@ -1,2 +1,3 @@
*.pyc
+.tmp*
View
No changes.
View
@@ -0,0 +1,91 @@
+from ecomstore.cart.models import CartItem
+from ecomstore.catalog.models import Product
+from django.shortcuts import get_object_or_404
+from django.http import HttpResponseRedirect
+
+import decimal # not needed yet but we will later
+import random
+CART_ID_SESSION_KEY = 'cart_id'
+
+# get the current user's cart id, sets new one if blank
+def _cart_id(request):
+ if request.session.get(CART_ID_SESSION_KEY, '') == '':
+ request.session[CART_ID_SESSION_KEY] = _generate_cart_id()
+ return request.session[CART_ID_SESSION_KEY]
+
+def _generate_cart_id():
+ cart_id = ''
+ characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij \
+ klmnopqrstuvwxyz1234567890!@#$%^&*()'
+ 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 from the current user's 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 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_distinct_item_count(request):
+ return get_cart_items(request).count()
+
+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
+
View
@@ -0,0 +1,19 @@
+from django import forms #this import should already be at the top
+
+class ProductAddToCartForm(forms.Form):
+ quantity = forms.IntegerField(widget=forms.TextInput(attrs={'size':'2',
+ 'value':'1', 'class':'quantity', 'maxlength':'5'}),
+ 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)
+
+ # custom validation to check for cookies
+ def clean(self):
+ if self.request:
+ if not self.request.session.test_cookie_worked():
+ raise forms.ValidationError("Cookies must be enabled.")
+ return self.cleaned_data
View
@@ -0,0 +1,28 @@
+from django.db import models
+from ecomstore.catalog.models import Product
+
+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:
+ 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):
+ self.quantity = self.quantity + int(quantity)
+ self.save()
View
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
View
@@ -0,0 +1,5 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('ecomstore.cart.views',
+ (r'^$', 'show_cart', { 'template_name': 'cart/cart.html' }, 'show_cart'),
+)
View
@@ -0,0 +1,17 @@
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from ecomstore.cart import cart
+
+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))
+
No changes.
@@ -0,0 +1,13 @@
+from django import template
+import locale
+
+register = template.Library()
+
+@register.filter(name='currency')
+def currency(value):
+ try:
+ locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
+ except:
+ locale.setlocale(locale.LC_ALL, '')
+ loc = locale.localeconv()
+ return locale.currency(value, loc['currency_symbol'], grouping=True)
@@ -0,0 +1,26 @@
+from django import template
+from ecomstore.cart import cart
+
+from ecomstore.catalog.models import Category
+
+from django.contrib.flatpages.models import FlatPage
+
+register = template.Library()
+
+@register.inclusion_tag("tags/cart_box.html")
+def cart_box(request):
+ cart_item_count = cart.cart_distinct_item_count(request)
+ return {'cart_item_count': cart_item_count }
+
+@register.inclusion_tag("tags/category_list.html")
+def category_list(request_path):
+ active_categories = Category.objects.filter(is_active=True)
+ return {
+ 'active_categories': active_categories,
+ 'request_path': request_path
+ }
+
+@register.inclusion_tag("tags/footer.html")
+def footer_links():
+ flatpage_list = FlatPage.objects.all()
+ return {'flatpage_list': flatpage_list }
View
@@ -2,6 +2,12 @@
from ecomstore.catalog.models import Category, Product
from django.template import RequestContext
+# this stuff goes at the top of the file, below other imports
+from django.core import urlresolvers
+from ecomstore.cart import cart
+from django.http import HttpResponseRedirect
+from ecomstore.cart.forms import ProductAddToCartForm
+
def index(request, template_name="catalog/index.html"):
page_title = 'Musical Instruments and Sheet Music for Musicians'
return render_to_response(template_name, locals(),
@@ -17,12 +23,34 @@ def show_category(request, category_slug,
return render_to_response(template_name, locals(),
context_instance=RequestContext(request))
+# 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.filter(is_active=True)
+ categories = p.categories.all()
page_title = p.name
meta_keywords = p.meta_keywords
meta_description = p.meta_description
- return render_to_response(template_name, locals(),
+ # 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:
+ # its 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))
View
@@ -1,4 +0,0 @@
-from django.shortcuts import render_to_response
-
-def home(request):
- return render_to_response("index.html")
View
@@ -61,6 +61,7 @@
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
'djangodblog.middleware.DBLogMiddleware',
)
@@ -83,6 +84,8 @@
'django.contrib.admin',
'ecomstore.catalog',
'ecomstore.utils',
+ 'ecomstore.cart',
+ 'django.contrib.flatpages',
'djangodblog',
)
View
@@ -111,4 +111,62 @@ div.product_image{
float:left;
padding:0 10px 10px 0;
}
+/* style for Django error messages */
+ul.errorlist{
+ background-color:Red;color:White;
+}
+
+/* styles for shopping cart page */
+table#shopping_cart{
+ width:100%;
+ border-collapse:collapse;
+ color:#616161;
+}
+h1,caption{
+ text-align:left;
+ font-size:x-large;
+ margin-bottom:15px;
+ color:Black;
+}
+th,td{
+ text-align:left;
+ padding:3px;
+}
+thead th{
+ color:White;
+ background-color:#616161;
+}
+tfoot th{
+ height:40px;
+}
+table#shopping_cart th.right, td.right{
+ text-align:right;
+}
+a.cart{
+ color:DarkOrange;
+}
+
+h3{
+ background-color:#98AC5E;
+ color:White;
+ padding:3px;
+ margin-bottom:6px;
+}
+ul#categories{
+ list-style:none;
+}
+ul#categories li{
+ font-weight:bold;
+ color:#616161;
+}
+ul#categories li a{
+ text-decoration:underline;
+}
+div#footer a{
+ color:White;
+ font-size:small;
+ text-decoration:underline;
+ font-weight:normal;
+ margin-right:10px;
+}
Oops, something went wrong.

0 comments on commit 9662dac

Please sign in to comment.