Beginning Django E Commerce
398 pág.

Beginning Django E Commerce


DisciplinaProgramação I24.614 materiais280.257 seguidores
Pré-visualização50 páginas
items ready for purchase. 
With the template and corresponding styles in place, we can now turn our attention on the last bit of 
code we need to write, which is our view code and the corresponding functions in our cart.py module. 
Open up your views.py file and change the show_cart() view function so that it looks like this: 
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(),\ufffd 
 context_instance=RequestContext(request)) 
And lastly, add the following four function definitions to the cart.py module, so that our view code 
actually has some corresponding code to call: 
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: 
www.it-ebooks.info
CHAPTER 4 \u25a0 THE SHOPPING CART 
 
101 
 
 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 
You should be starting to get the hang of the flow at work here, and hopefully, the preceding code is 
making some sense to you. Most of the code in our cart.py module is stuff that would have been put in 
the would-be \u201ccart\u201d model, if we had chosen to create two separate models. For example, one of the 
preceding methods, cart_subtotal(), is returning the subtotal of the user\u2019s cart for display on the page. 
Logically, this would have gone in the cart model if we had created one, and we would call this method 
on the instance of our user\u2019s cart. 
Have a look at the forms that are on the cart page. Here, I\u2019ve opted to build them from scratch 
instead of coding up Django form classes to create them for us. One of them takes one quantity input, 
very similar to our product page, and updates the quantity in the cart. If the quantity is zero on an 
update submission, than we simply delete the item from the cart. The other form contains a Remove input 
that removes the item from the cart. 
Adding Custom Template Tags 
One last thing that we need to add is a link somewhere at the top of the page that links to the cart, so our 
browsing users are free to check out whenever they would like. We\u2019re going to create a custom Django 
template tag to contain our \u201cLink to Cart\u201d box. We\u2019ll have this information display at the top right in the 
banner, inside an absolutely positioned div element. Create a new include template file called 
cart_box.html inside your project\u2019s template/tags directory. Add the following markup to it: 
{% with cart_item_count as cart_count %} 
 <a href=&quot;{% url show_cart %}&quot;> 
 Shopping Cart 
 <br /> 
 {{ cart_count }} Item{{ cart_count|pluralize }} 
 </a> 
{% endwith %} 
www.it-ebooks.info
CHAPTER 4 \u25a0 THE SHOPPING CART 
 
102 
 
Remember when we used the built-in urlresolvers.reverse() method to fetch the URL location of 
the cart page? Turns out, you can use a Django template {% url %} tag to achieve the same thing in your 
templates. We pass it the string show_cart and it finds the corresponding URL definition in our urls.py 
modules. Pretty slick, eh? 
We\u2019re also using a new Django tag: {% with %}. The Django {% with %} tag allows you to give a 
variable an alias and cache it in the template, so that your database isn\u2019t hit with the query to get the 
number of items in the cart each time a new page is loaded. Here, we\u2019re assigning the value of 
cart_item_count to a variable called cart_count, and using that variable in our actual template code. 
Lastly on the template side of things, we need to load our new templates and insert the tag in the 
appropriate spot. Add the following line of code near the top of your template: 
{% load catalog_tags %} 
And then add this to your catalog.html, inside the cart_box div: 
<div class=&quot;cart_box&quot;> 
 {% cart_box request %} 
</div> 
Here, we\u2019re calling on our new cart_box template tag and passing in the current request object as a 
variable. Now we get to the real Django magic. Inside your catalog app\u2019s templatetags directory, right 
alongside your catalog_filters.py module, create a new module called catalog_tags.py. This file will 
contain the functions for our template tags. Open up catalog_tags.py and add in the following lines of 
Django code: 
from django import template 
from ecomstore.cart import cart 
 
register = template.Library() 
 
@register.inclusion_tag(&quot;tags/cart_box.html&quot;) 
def cart_box(request): 
 cart_item_count = cart.cart_distinct_item_count(request) 
 return {'cart_item_count': cart_item_count } 
In the inclusion_tag() function call, you pass in the name of the template file you want to use, 
which in our case is the cart_box.html file we just created. Our template function tags the request object 
as a parameter (which we passed in our use of the tag in the template) and then returns a Python 
dictionary of variables that our template will be able to use. You can see that this is how our template is 
getting the cart_item_count variable we aliased and used in our actual template file. 
With these simple changes, we now have a link to our Shopping Cart page on every page of our site, 
which also tells the user how many distinct products are in their cart. We\u2019re also making good use of the 
Django pluralize template filter and the excellent {% with %} tag. 
www.it-ebooks.info
CHAPTER 4 \u25a0 THE SHOPPING CART 
 
103 
 
 
Figure 4-4. Site banner, now with cart page link. 
Re-creating the Category List Tag 
Keep that new catalog_tags.py file open, because we\u2019re not done with it quite yet. We can apply this 
same template tag logic to the list of categories that we\u2019re using in the sidebar of each page, and, at the 
same time, make a couple of improvements. First, we can use this new {% with %} tag to cache our list of 
categories and save a hit to the database on each one. On top of that, we\u2019ll set up some logic so that if the 
user is currently on a category page, we\u2019ll deactivate the link to give the user a small visual cue about 
where they are. 
As long you\u2019ve got it open, add the following code to your catalog_tags.py file: 
from ecomstore.catalog.models import Category 
 
@register.inclusion_tag(&quot;tags/category_list.html&quot;) 
def category_list(request_path): 
 active_categories = Category.objects.filter(is_active=True) 
 return { 
 'active_categories': active_categories, 
 'request_path': request_path 
 } 
Now, open up the category_list.html file you created back in Chapter 3 and change its contents to 
the following: 
<h3>Categories</h3> 
<ul id=&quot;categories&quot;>