现在,我们有了一个产品目录界面,用户如果看到满意的产品,就可以将其放入购物车。下面就让我们来实现购物车的功能。

首先要做一下简单的分析和设计。购物车应该显示一系列产品的清单,其中列出了买方选中的产品。但是这个清单没有必要马上保存到数据库,因为直到付款之前,用户随时都有可能改变主意。我们只需要在用户的session中记录这些产品就可以了。

购物车中的条目
购物车中的条目与产品(Product)

类似,但是我们没有必要将这些信息再重复记录一次,而只需要让条目关联到产品即可。此外在条目中还会记录一些产品中没有的信息,比如数量。最后,我们想要

在条目中记录一下单价——虽然产品中包含了价格信息,但是有时候可能会有一些折扣,所以需要记录下来用户购买时的价格。基于这些分析,我们设计了条目这一
模型类:

class LineItem(models.Model):
product = models.ForeignKey(Product)
unit_price = models.DecimalField(max_digits=,decimal_places=)
quantity = models.IntegerField()

购物车

购物车是这些条目的容器。我们希望实现一个“聪明的”购物车,它可以有自己的一些行为:比如,如果放入已经有的产品,就更改该产品的数量而不是再增加一个

条目;能够查询当前购物车中的产品数量,等等。所以购物车也应该是一个模型类。但是与LineItem不同,购物车并不需要记录到数据库中,就好像超市并
不关注顾客使用了哪量购物车而只关注他买了什么商品一样。所以购物车不应该继承自models.Model,而仅仅应该是一个普通类:

class Cart(object):
def __init__(self, *args, **kwargs):
self.items = []
self.total_price =
def add_product(self,product):
self.total_price += product.price
for item inself.items:
if item.product.id == product.id:
item.quantity +=
return
self.items.append(LineItem(product=product,unit_price=product.price,quantity=))

在我们设计模型的同时,界面设计师也为我们设计好了购物车的界面:

接下来就可以实现url映射,view函数和模板。首先我们希望购物车的url为”http://localhost:8000/depotapp/cart/view/“,这需要在depotapp/urls.py的urlpatterns中增加一行:

 (r'cart/view/', view_cart),

然后在depotapp/views.py中定义视图函数。注意购物车是保存在session中的,需要通过request.session.get获取:

def view_cart(request):
cart = request.session.get("cart",None)
t = get_template('depotapp/view_cart.html')
ifnot cart:
cart = Cart()
request.session["cart"] = cart
c = RequestContext(request,locals())
return HttpResponse(t.render(c))

最后实现模板界面:

  {% extends "base.html" %}
{% block title %} 我的购物车{% endblock %}
{% block pagename %} 我的购物车 {% endblock %}
{% block content %}
<divclass="row">
<divclass="span10">
<tableclass="condensed-table">
<thead>
<tr>
<thclass="header">数量</th>
<thclass="yellow header">名称</th>
<thclass="blue header">单价</th>
<thclass="green header">小计</th>
</tr>
</thead>
<tbody>
{% for item in cart.items %}
<tr>
<th>{{item.quantity}}</th>
<td>{{item.product.title}}</td>
<td>{{item.unit_price}}</td>
<td>{% widthratio item.quantity item.unit_price %} </td>
</tr>
{% endfor %}
<tr>
<th></th>
<td></td>
<th>总计:</th>
<th>{{cart.total_price}}</th>
</tr>
</tbody>
</table>
</div>
<divclass="span4">
<p><aclass="btn primary span2"href="#">继续购物</a></a></p>
<p><aclass="btn danger span2"href="#">清空购物车</a></p>
<p><aclass="btn success span2"href="#">结算</a></p>
</div>
</div>
{% endblock %}

这里面有一个技巧。因为Django模板的设计理念是”业务逻辑应该和表现逻辑相对分开“,所以在Django模板中不建议执行过多的代码。在计算 条目小计的时候,使用的是Django模板的widthratio标签。该标签的原意是按比例计算宽度:根据当前值(this_value)和最大值 (max_value)之间的比例,以及最大宽度(max_width)计算出当前的宽度(this_width),即{% widthratio this_value max_value max_width %} = max_width * this_value / max_value。但是如果我们设定max_value=1,就可以通过width ratio在Django模板中进行乘法计算了。同理还可以进行除法计算。而总计价格的计算是通过模型(Cart)类实现的。

为Django增加session支持

好了,我们已经做了大量的工作,现在让我们欣赏一下自己的作品。但是启动server并访问http://localhost:8000 /depotapp/cart/view/时,却提示”找不到django_session表“。这是因为Django对session的支持是通过内置 的django.contrib.sessions应用实现的,该应用会将session数据保存在数据库中。但是创建project是Django并没 有默认安装该app——Django不会瞒着你做任何事情。所以如果我们”显式地“决定要使用session,需要更改project的设置,在 depot/settings.py的INSTALLED_APPS中去掉session的注释:

 INSTALLED_APPS = (
#'django.contrib.auth',
#'django.contrib.contenttypes',
'django.contrib.sessions',
#'django.contrib.sites',
#'django.contrib.messages',
#'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'depot.depotapp',
'django-groundwork',
)

然后还要同步一下数据库:

$ python manage.py syncdb
Creating tables ...
Creating table django_session
Installing custom SQL ...
Installing indexes ...
No fixtures found.

这是再启动服务器,就可以看到我们实现的购物车了。但是这个购物车能看不能用,无法将商品加入购物车,也无法从中去掉商品。下一节,让我们继续完善购物车的功能。

Django实战(13):在session中保存购物车的更多相关文章

  1. ThinkPHP模板中如何操作session,以及如果session中保存的是数组的情况

    在ThinkPHP的模板中操作session时,可以参考ThinkPHP参考文档中的“模板—>系统变量”部分,在默认模板引擎中,语法如下: {$Think.session.user} //输出s ...

  2. Tomcat关闭后,重新启动,session中保存的对象为什么还存在解决方法

    Tomcat关闭后,重新启动,session中保存的对象为什么还存在各们朋友大家好:         当我关闭Tomcat,重新启动后,session中保存的对象还依然存在,仍然可以使用,不知这是什么 ...

  3. JS或jsp获取Session中保存的值

    JS是不能读取Session中的值的 . session是服务器对象, javascript是客户端脚本,你能做的操作就是把这个值用 <%=%>输出到页面的javascript中参与运算, ...

  4. thinkphp中cookie和session中操作数组的方法

    thinkphp中cookie和session中操作数组的方法 一.ThinkPHP模板中如何操作session,以及如果session中保存的是数组的情况 在ThinkPHP的模板中操作sessio ...

  5. session中用户信息改变问题

    问题描述: 在web项目中,我们经常将用户登录信息放在session中用来做后续的权限判断等操作,但最近在项目中发现一个奇怪的现象,session中的用户信息和登录时的信息有了差异. 原因: 在后台代 ...

  6. 关于在页面得到的servlet验证码总是上一次保存在session中的

    在网上找到一份servlet产生验证码的代码,经过测试,发现在页面通过session.getAttribute()方法得到的验证码总是上一次保存在session中的,这样,它总比页面实际的验证码晚一拍 ...

  7. Django实战(一)-----用户登录与注册系统6(session会话、注册视图)

    因为因特网HTTP协议的特性,每一次来自于用户浏览器的请求(request)都是无状态的.独立的. 通俗地说,就是无法保存用户状态,后台服务器根本就不知道当前请求和以前及以后请求是否来自同一用户.对于 ...

  8. 13 Django组件-cookie与session

    会话跟踪技术 1 什么是会话跟踪技术 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而10 ...

  9. Java实现购物车功能:方式一:存放在session中.方式二:存储在数据库中

    //将购物车产品加入到cookie中,方式同浏览记录.Java实现购物车,方式一(简易版):存储在session中.这种方式实现还不严谨,大家看的时候看思路即可.(1). JSP页面中,选择某一款产品 ...

随机推荐

  1. 科学计算三维可视化---TraitsUI的介绍

    TraitsUI的介绍 Python中存在Tkinter,wxPython,pyQt4等GUI图像界面编写库,这三类库要求程序员掌握众多的GUI API函数 对于科学计算的应用来说,我们希望可以快速的 ...

  2. vue 脚手架使用

    1. npm指令 vue init 模板类型   项目名称 如: vue init webpack-simple mydemo 2.进入刚才生产的 文件夹 mydemo cd mydemo 3.初始化 ...

  3. What Does “Neurons that Fire Together Wire Together” Mean?

    What Does “Neurons that Fire Together Wire Together” Mean? I’ve heard the phrase “neurons that fire ...

  4. @Controller,@Service,@Repository,@Component详解

    @Controller 用来表示一个web控制层bean,如SpringMvc中的控制器. @Service 用来表示一个业务层bean. @Repository 用来表示一个持久层bean,即数据访 ...

  5. virtual Box在Centos 7上的安装

    1.首先,我们需要在oracle官网下载virtual Box的centos7版本: 下载地址为:http://download.virtualbox.org/virtualbox/5.0.12/Vi ...

  6. 【leetcode 简单】 第八十八题 猜数字大小

    我们正在玩一个猜数字游戏. 游戏规则如下: 我从 1 到 n 选择一个数字. 你需要猜我选择了哪个数字. 每次你猜错了,我会告诉你这个数字是大了还是小了. 你调用一个预先定义好的接口 guess(in ...

  7. Go语言的接口interface、struct和组合、继承

    Go语言的interface概念相对于C++中的基类,通过interface来实现多态功能. 在C++中,当需要实现多态功能时,步骤是首先定义一个基类,该基类使用虚函数或者纯虚函数抽象了所有子类会用到 ...

  8. 关于注入抽象类报could not autowire field的问题

    昨天工作中遇到了一个很奇葩的问题,之前一直都没考虑过抽象类这块,一直用的注入接口实现类: 先看下错误: 因为在类中注入了一个抽象类,之前只有一个继承子类,所以没问题,这里要说一下抽象类的实例化: 抽象 ...

  9. perl6: hash小笔记

    > ,,, { => , => } > my $a = :%h h => { => , => } > $a.perl :h({, }) > my ...

  10. shell变量$#,$@,$0,$1,$2的含义

    linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...