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

首先要做一下简单的分析和设计。购物车应该显示一系列产品的清单,其中列出了买方选中的产品。但是这个清单没有必要马上保存到数据库,因为直到付款之前,用户随时都有可能改变主意。我们只需要在用户的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. HTTP协议(4):CGI

    CGI接口原理及实现(2012-12-7 Over) 1.CGI定义: CGI(CommonGateway Interface)是HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须 ...

  2. Ubuntu16.04.2安装Tensorflow

    安装aptitude $ sudo apt-get install aptitude 安装python-pip python-dev $ sudo aptitude install python-pi ...

  3. [NOI1997] 积木游戏

    COGS 261. [NOI1997] 积木游戏 http://www.cogs.pro/cogs/problem/problem.php?pid=261 ★★   输入文件:buildinggame ...

  4. XML学习(1)

    什么是XML? XML是可拓展标记语言,类似HTML,它的设计宗旨是为了传输数据,而不是像HTML那样显示数据.XML标签没有被预定义,需要用户自定义标签. xml文档必须包含根元素,它是其他所有元素 ...

  5. window对象中的一些重要的属性和方法(笔记)

    setTimeout()方法用来实现一个函数在指定的毫秒数之后运行:setTimeout()返回一个值,这个值可以传递给clearTimeout()用于取消这个函数的执行.由于历史原因,setTime ...

  6. 如何给自己的PHP项目制作安装程序

    最近很是激动啊,现在的自己还是和当初刚刚学习程序的时候一样,虽然现在回头一看自己写过的程序,都非常的小孩子和漏洞百出,也没有太多的考虑效率和安全,但是还是每次写出了新的程序或系统,都是抱着一种马上拿着 ...

  7. SQL Server 数据库备份失败解决方法

    问题:System.Data.SqlClient.SqlError: 无法使用备份文件 'D:\20160512.bak',因为原先格式化该文件时所用扇区大小为 512,而目前所在设备的扇区大小为 4 ...

  8. 基于Ubuntu搭建GMS测试环境

    一.版本信息: 系统版本:Ubuntu 18.04.2 LTS JDK版本: 1.8.0_171 SDK版本:android-sdk_r24.4.1-linux.tgz ADB版本:1.0.40 ap ...

  9. python装饰器三种装饰模式的简单理解

    学设计模式中有个装饰模式,用java实现起来不是很难,但是远远没有python简单,难怪越来越火了! 这里就简单讨论下python的几种装饰模式: 一 无参装饰器: # 装饰器 import time ...

  10. 【LinuxC】GCC编译C程序,关闭随机基址

    1.编译.链接和运行程序 C代码示例: #include <stdio.h> #include <stdlib.h> int main() { printf("hel ...