B2C的电商网站
首先分析客户需求,做电商网站我们需要哪些功能模块。设计数据库表、字段、属性。现在这个电商网站运用django框架,采用前后端不分离的方式,拥有用户模块、订单模块、购物车模块、商品模块四个模块。
用户模块
注册
-
显示注册页面;
-
用户注册处理:在注册页面需要获取到数据传给views视图,views视图里面的接口函数进行注册,注册的时候需要获取到用户名、密码、邮箱。校验为空就提示用户数据不完整。同时校验邮箱是否合法,如果不合法的话,提示用户邮箱不合法。注册时用户输入的密码是明文,如果存在数据库是明文的话,数据不安全,所以用Hashlib中的sha1对密码进行加密;
-
发送邮件:因为django中已封装发送邮件函数,但是属于同步,影响用户的体验。所以我们使用celery进行异步发送邮件。获得到项目序列号以及用户ID进行签名加密,使用itsdangerous对邮件进行加密dumps;
-
点击发送的激活链接:需解密loads序列号,获得到用户ID进行激活,并保存到数据库中。激活成功会跳转到登录页面,否则提示用户激活链接已经过期;
-
判断用户名是否存在,如果存在就提示更换用户名,如果不存在,可进行注册。返回给前端json数据,json数据返回存在就提示用户名已存在,反则就提示注册步骤。在前端页面上编写前端的代码获取到用户名,发起ajax请求,判断用户名是否存在,根据返回的json数据进行判断,存在的话,就显示用户名存在,让用户名的输入框为错误,否则输入框正确,但是这里就需要改成ajax同步请求,判断完之后变为异步请求;
登陆
-
判断cookie信息是否存在用户名,如果存在则去除用户名,复选框的值,返回给前端页面,显示登陆页面;
-
判断用户是否登录,获取到用户名、密码以及复选框值,校验数据,若数据为空则提示用户数据不完整,从数据库中查找出用户名、密码一致的数据。查询到用户数据则判断是否记住用户名,如果需要记住用户名则设置保存(set_cookie)cookie信息,如果不记住则删除掉(delete_cookie)cookie的信息。在这里还需要通过session信息保存用户未登录前的浏览纪录,用到一个保存用户刚才浏览信息的中间件,但有些浏览纪录不需要记录(比如注册、退出、登录、还有ajax请求,get请求),其余纪录需要保存。如果没有需纪录则直接跳转首页,在这里还需要通过session记住用户名、用户ID、用户登录状态,否则提示用户名和密码不正确;
-
有些页面需用户登录才能访问,我们定义一个用来判断用户是否登录的装饰器。检测session信息保存的用户是否为登录状态,如果是登陆状态则能够查看登录后的页面,反之返回到首页。
用户中心-地址页:session中用户ID,如果访问方式是get则显示地址页面,查询用户的默认地址,返回到用户的地址信息页面,否则就添加收货地址,获取到用户的用户名、地址、手机号码,校验数据是否完整,添加收货的地址,返回数据到地址页面; -
用户中心的订单页:查询订单信息,从session获取用户ID,通过用户ID获取到所有订单信息,遍历算出每个订单商品的信息,从数据库中获取到商品数量及价格,计算出商品价格,保存订单中每一个商品信息。动态给订单表添加属性,保存订单的商品的信息,把订单信息返回给前端页面,前端页面去通过后台返回的数据,对页面进行修改,这里需要把所有的订单给显示出来,所以要for循环遍历订单信息,但是这里需要注意订单信息是一个对象,而动态添加的属性也是一个对象;
-
用户中心的信息页:查询用户的浏览纪录,首先从session里获取用户ID,通过ID在数据库中获取到用户基本信息,获取用户最近浏览纪录。由于最近浏览信息保存在redis数据库,所以使用到django_redis的get_redis_connection连接到redis数据库。通过redis数据库的历史纪录,使用lrange获取用户浏览5个商品信息,遍历5个商品的ID,查询数据库的商品表内对应的商品信息,将商品的列表、地址信息传给前端,前端通过遍历显示用户最近浏览纪录;
-
退出登录:清空用户session信息,通过flush删除存在redis数据库中信息,跳转到首页。
商品模块
首页
- 商品模块分析,我们的网站是首页展示为4个高销量产品以及3个新品,查找数据传给前端页面。
详情页
- 随机点开一个商品详情页面:
- 获取商品的详细信息,判断商品是否存在,如果不存在则跳转到首页,反之获取商品图片。判断是否存在图片(exists),有图片就取第一张,反之则返回空值。商品的详情表还需要展示2个新品推荐,所以在商品表查询出2个新品信息。
- 纪录用户浏览历史,但用户登录之后才会纪录浏览历史。首先判断session里是否为登录状态,用户登录则链接redis数据库用Hash存储,设置一个key键保存用户浏览纪录,用户有可能浏览同一个商品,所以先从redis列表里面移除lrem商品的ID。再从坐标lpush添加1条商品ID,保存ltrim用户最近浏览的5个商品。
- 把商品信息、列表、图片传给前端页面并渲染显示。获取商品的价格和数量,计算商品总价,设置商品的总价显示。
- 点击+,触发click事件,获取到商品的数量进行加1,重新设置值并计算总价。点击-,触发click事件,获取商品数量进行减1,注意需要判断不能小于1,若小于则重新设置为1,计算总价。还可以手动输入触发一个click事件,获取商品数量,判断是数字且不能小于1,而且输入其他内容都等于1,重新设置商品的数量并计算总价。
商品列表页面控制
- 获取商品排序方式,如果没有排序方式则默认排序。判断商品种类ID是否在商品种类里,如果不在则跳转到首页,否则根据商品种类和排序方式查询数据库的商品信息,并分页展示。分页使用django.core.paginator中的Paginator类,对商品进行分类,创建的对象可以通过num_pages方法获取到分页之后的总页数,获得到的页数如果大于总页数或者获得总页数为空,就等于1,否则就等于获得的页数。使用page方法,返回Page类的实例对象,这里还要用到了对页码进行了一个的话,当前页是前三页则就显示1-5页,当前页是后三页,显示后5页,其他情况就显示,当前页的前两页,当前页的后两页,在这里还需要获取到两个新品推介,去数据库里面查询出两个信息,商品的标题可以通过商品的种类ID获得到商品名称。
搜索页面
搜索框需要进行搜索,搜索使用到haystack搭建用户和搜索引擎值间的沟通问题,whoosh对分词进行操作。但是需要引入中文,用结巴分词进行查找,使用 python manage.py rebuild_index 生成索引文件,搜索出结果后,haystack会把搜索出来的结果传给template/search目录下的search.html文件,所搜表单的name必须为q,传page当前页的page对象,paginator分页的paginator对象,通过HAYSTACK_SEARCH_RESULTS_PER_PAGE 可以控制每页显示数量;
购物车模块
- 点击商品页面加入购物车:
- 想在购物车里添加数据,首先判断用户是否登录,如果没有登录则返回json数据,提示用户登录,接受数据获取用户ID及数量,进行校验判断接受的数据是否完整。通过获取到商品ID查询数据库,判断商品是否存在,如果不存在返回json数据,提示商品不存在,将获取到商品的数量转化成整数,注意可能会出现异常,告诉用户必须为数字。
- 将商品添加到购物车,每个用户的购物车纪录是一条hash数据进行保存,连接redis数据库设置key值,通过查询redis数据库中商品,进行判断。如果之前有此商品就对数目加1,如果无此商品则添加数据。
- 还需要通过查询出来的数据进行判断是否大于库存,如果大于则返回json数据,提示用户库存不足,否则保存到数据库中并返回数据。再进行前端修改,触发一个click事件,获取到商品ID、数量,发送post请求,判断json数据,获取到原有的商品购物车值,进行相加,最后做一个显示,否则添加失败,打印出错误的原因;
- 显示购物车页面:
- 用户必须是登陆状态,所以用验证装饰器对购物车页面进行装饰,获取到用户的ID、用户购物车纪录,因为购物车的商品ID以及数量已经被保存在redis数据库,可以通过用户ID就能够获取购物车中用户添加的信息。
- 遍历所有的购物车信息,获取商品ID以及数量,通过ID去查询数据库中商品信息,保存商品数目。通过商品数目和商品价格,保存商品小计,可以将商品信息保存到列表中,算出商品的总数量及总价格,把商品列表数量总价格传给前端。前端通过遍历商品列表,进行一个显示,计算出商品总计、小计,最后进行设置。
- 但是判断是否是全选,获取所有被选中的商品,计算小计和总价数量,设置商品的总价和总数目。全选和全不选,首先获取全选cleckbox的状态,遍历所有商品对应的checkbox,设置checked属性和全选的checkbox一致,更新商品的信息,商品对应的checkbox状态发生改变,全选checkbox改变,获取到所有商品对应的checkbox数目,获取选中的商品的checkbox数目,进行比较,之后再进行更新商品的信息。
-
获取用户购物车商品数目,判断用户是否登录,如果没有登录返回json数据0,计算用户购物车商品数量,因为商品数量都保存在redis数据库中,所以通过redis数据库进行查询,这是通过hvals获取到所有的商品数量,进行遍历,计算返回结果,在商品上的购物车数量进行显示,更新购物车总数目。
-
更新购物车商品数目,判断用户是否登录,接收数据,获取到商品数量以及商品ID,进行数据校验,根据获取到商品ID,判断商品是是否存在,对商品的数量进行转化成整数类型,捕获异常,更新操作,因为商品的数量、ID保存在redis数据库,连接redis数据库,判断商品的库存,在对商品进行一个设置,返回结果,前端页面通过判断返回的json数据,进行判断,点击增加、减少、手动输入按钮,获取到商品数目和商品的ID,更新购物车信息,保存更新状态。如果成功更新返回更新状态,不成功打印错误信息,注意这里ajax请求是异步的,所以有可能没有判断完成就会执行其他的操作,就需要把ajax请求设置为同步。判断完成之后再设置为异步请求,如果状态是一样的话,获取到商品的数量,获取商品对应的checkbox的选中状态.根据商品被选中的状态更新商品的总数目或者小计,手动输入需要对商品的数量进行判断。
-
删除购物车商品信息:判断用户是否登录,接收数据,校验对商品是否存在,如果存在则通过连接redis数据库,hdel删除商品ID,返回json数据,对前端进行操作,获取要删除商品ID,对返回的json数据进行判断,成功则删除整条URL,判断商品是否被选中的状态,如果选中的话,就更新商品的总数目及小计,否则只更新商品的小计。
订单模块
显示提交订单页面
- 接收数据获取到所有商品ID,校验数据,判断数据能收到,如果收不到则跳转到购物车页面,session中获取用户ID,在数据库里查询地址信息,获取用户预购买的商品信息。用户要购买的商品保存在redis数据库,连接redis数据库遍历所有商品ID,根据商品ID获取到商品信息,获得商品数量计算商品小计,动态更新商品信息,添加小计和数量这两个属性,将用户购买信息放到列表,计算商品的运费和实付款,将获得数据传给前端并展示。
提交订单信息
- 提交订单信息:向两张表里添加数据需要用到事务,验证用户是否登录,接收数据,接收商品id\addr_id\pay_method(支付方式),校验数据的完整性,通过addr_id取数据库的地址表数据,捕获异常信息,判断支付方式是否属于构建的支付方式,订单创建,组织订单信息,获取到用户ID,订单ID是由datetime.now().strftime('%Y%M%D%H%M%S')+str(passport_id)构建出来,运费、订单商品总数和金额。同时构建一个保存点,在向订单信息中添加纪录,刚开始商品总数以及总金额初始值为0,向订单商品表里添加订单商品纪录,遍历商品的ids,根据商品ID查询商品信息,如果商品信息有误,对事务进行回滚操作。通过查询redis数据库获取用户要购买的商品数量,判断商品库存,创建一条订单商品纪录,增加商品销量,减少商品库存,保存商品的信息,累计计算商品的总数量和金额,更新订单的商品总数目和总金额,如果数据库操作失败,进行回滚,最后消除购物车的纪录,对事务进行提交,返回应答,在前端页面上发起post的请求,根据json数据进行处理判断,跳转到用户中的订单信息;
订单支付
判断用户登录,接收订单ID,数据校验,通过订单ID、支付的状态、支付的方式查询数据库中订单信息和支付宝进行交互,电脑网站支付,跳到支付宝提供的连接,计算出要支付的金额,通过alipay.api_alipay_trade_page_pay()进行支付,返回给用户一个应答。
获取用户支付结果,判断用户是否登录,获取到用户ID,接受订单ID,进行数据校验,和支付宝进行交互,通过alipay.api_alipay_trade_query()进行支付结果的查询,判断支付结果等于10000的话并且支付的状态是trade_success。说明支付宝支付订单成功,支付成功保存在订单信息中。如果支付的结果是10000且提示是wall_buyer_pay的话,等待支付,继续查询,否则就是支付失败,返回json数据为1,提示网站用户支付失败。
做好这个电商网站我们下载的软件有:
amqp==2.1.4
appdirs==1.4.3
billiard==3.5.0.2
celery==4.0.2
Django==1.8.7
django-haystack==2.6.0
django-redis==4.8.0
django-redis-sessions==0.5.6
django-tinymce==2.6.0
itsdangerous==0.24
jieba==0.38
kombu==4.0.2
packaging==16.8
Pillow==3.4.1
pkg-resources==0.0.0
pycryptodome==3.4.7
pymongo==3.4.0
PyMySQL==0.7.10
pyparsing==2.2.0
python-alipay-sdk==1.4.0
pytz==2016.10
redis==2.10.5
six==1.10.0
uWSGI==2.0.15
vine==1.1.3
Whoosh==2.7.4
网友评论