新星计划Django基于PythonWeb的Django框架设计实现天天生鲜系统-8商品详细页面与商品分类功能实现
Posted Vax_Loves_1314
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了新星计划Django基于PythonWeb的Django框架设计实现天天生鲜系统-8商品详细页面与商品分类功能实现相关的知识,希望对你有一定的参考价值。
商品详细页面功能实现
商品详细页面需要展示的数据为, 商品分类和具体商品数据. 我们在 goods 应用的 views.py 模块中新增视图函数 detail, 用于处理商品详细信息显示. 代码实现如下:
def detail(request):
"""商品详细页面"""
# 获得产品ID
goods_id = request.GET.get('id', 1)
# 查询该商品
goods_data = GoodsInfo.objects.get(id=goods_id)
# 查询商品分类
categories = GoodsCategory.objects.all()
# 读取购物车商品列表
cart_goods_list = []
# 商品总数
cart_goods_count = 0
for goods_id, goods_num in request.COOKIES.items():
if goods_id == 'csrftoken':
continue
cart_goods = GoodsInfo.objects.get(id=goods_id)
cart_goods.goods_num = goods_num
cart_goods_list.append(cart_goods)
# 累加购物车商品总数
cart_goods_count = cart_goods_count + int(goods_num)
return render(request, 'detail.html', {'categories': categories,
'goods_data': goods_data,
'cart_goods_list': cart_goods_list,
'cart_goods_count': cart_goods_count})
当我们请求的网址为: localhost:8000/detail/?id=100 时, Django 会自动将问号(?)后面的参数解析, 并存储在 request.GET 字典中. 我们获取了商品的ID, 根据 ID 到数据库中查询该商品数据. 并在模板中显示.
detail.html 模板代码如下:
...
<div class="navbar_con">
<div class="navbar clearfix">
<div class="subnav_con fl">
<h1>全部商品分类</h1>
<span></span>
<ul class="subnav">
{% for cag in categories %}
<li><a href="/goods/?cag={{ cag.id }}&page=1" class="{{ cag.cag_css }}">{{ cag.cag_name }}</a></li>
{% endfor %}
</ul>
</div>
</div>
</div>
<div class="breadcrumb">
<a href="#">全部分类</a>
<span>></span>
<a href="#">{{ goods_data.goods_cag.cag_name }}</a>
<span>></span>
<a href="#">商品详情</a>
</div>
<div class="goods_detail_con clearfix">
<div class="goods_detail_pic fl"><img src="/static/{{ goods_data.goods_img }}"></div>
<div class="goods_detail_list fr">
<h3>{{ goods_data.goods_name }}</h3>
<br>
<div class="prize_bar">
<span class="show_pirze">¥<em>{{ goods_data.goods_price }}</em></span>
<span class="show_unit">单 位:{{ goods_data.goods_unit }}</span>
</div>
<div class="goods_num clearfix">
<div class="num_name fl">数 量:</div>
<div class="num_add fl">
<input type="text" class="num_show fl" value="1" disabled>
</div>
</div>
<div class="operate_btn">
<a href="/cart/add_cart/?id={{ goods_data.id }}" class="add_cart" id="add_cart">加入购物车</a>
</div>
</div>
</div>
<div class="main_wrap clearfix">
<ul class="detail_tab clearfix">
<li class="active">商品介绍</li>
</ul>
<div class="tab_content">
<dl>
<dd>{{ goods_data.goods_desc }}</dd>
</dl>
</div>
</div>
...
在 ttsx 目录下的 urls.py 模块中, 配置该视图函数和网址之间的对应关系.
from django.conf.urls import include, url
from django.contrib import admin
from goods.views import index # 导入视图函数
from goods.views import detail
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^index/$', index),
url(r'^detail/$', detail),
]
本页面除了展示商品的详细信息之外, 分类信息, 当用户点击"加入购物车"按钮, 会将产品信息加入购物车. 我们在模板中创建了加入购物车的连接, 代码如下:
<a href="/cart/add_cart/?id={{ goods_data.id }}" class="add_cart" id="add_cart">加入购物车</a>
我们在 cart 应用下的 views.py 模块中, 新增 add_cart 视图函数, 代码实现如下:
def add_cart(request):
"""添加商品到购物车"""
# 获得商品ID
goods_id = request.GET.get('id', '')
if goods_id:
# 获得上一页面地址
prev_url = request.META['HTTP_REFERER']
# 写入到 cookie 中
response = redirect(prev_url)
# 判断商品是否存在
goods_count = request.COOKIES.get(goods_id, '')
if goods_count:
goods_count = int(goods_count) + 1
else:
goods_count = 1
response.set_cookie(goods_id, goods_count)
return response
然后在 ttsx/urls.py 模块中配置该视图函数和网址之间的对应关系, 配置如下:
from django.conf.urls import include, url
from django.contrib import admin
from goods.views import index # 导入视图函数
from goods.views import detail
from cart.views import add_cart
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^index/$', index),
url(r'^detail/$', detail),
url(r'^cart/add_cart/$', add_cart),
]
我们的购物车是通过 cookie 来实现的, 首先我们获得要加入购物车的商品ID, 代码如下:
goods_id = request.GET.get('id', '')
然后获得上一页面的地址, 在 request 对象的 META 字典中保存了用户访问的上一页面地址, 代码如下:
prev_url = request.META['HTTP_REFERER']
当处理完购物车添加之后, 我们希望页面跳回到上一页面. 所以我们通过快捷函数 redirect, 创建另一个重定向响应, 该函数接收一个参数, 参数为要跳转的页面地址, 返回的响应对象类型为 HttpResponseRedirect, 该对象为 HttpResponse 的子类. 代码如下:
response = redirect(prev_url)
然后判断当前要添加的商品ID是否已经在购物车中存在, 如果存在则更新商品数量, 如果不存在则新增一条cookie 信息, 代码如下:
goods_count = request.COOKIES.get(goods_id, '')
if goods_count:
goods_count = int(goods_count) + 1
else:
goods_count = 1
最终将商品添加到 cookie 中, 代码如下:
response.set_cookie(goods_id, goods_count)
当返回该重定向响应之后, 浏览器会重新请求上一页面地址, 完成页面跳转.
return response
商品分类页面功能实现
-
该页面主要实现当点击首页分类链接、或者商品详细页面的分类链接, 会显示当前分类下的所有商品.
-
对显示的商品数据进行分类.
我们在 goods 应用中的 views.py 模块中的 goods 视图负责展示分类商品数据. 该视图函数接收2个参数:
-
当前分类是那个?
-
显示第几页数据?
goods 视图函数实现如下:
def goods(request):
"""商品展示页面"""
# 获得当前分类
cag_id = request.GET.get('cag', 1)
# 获得当前页码
page_id = request.GET.get('page', 1)
# 查询所有数据
goods_data = GoodsInfo.objects.filter(goods_cag_id=cag_id)
# 数据分页
paginator = Paginator(goods_data, 12)
# 获得当前页码数据
page_data = paginator.page(page_id)
# 查询商品分类
categories = GoodsCategory.objects.all()
# 查询当前商品分类
current_cag = GoodsCategory.objects.get(id=cag_id)
# 读取购物车商品列表
cart_goods_list = []
# 商品总数
cart_goods_count = 0
for goods_id, goods_num in request.COOKIES.items():
if goods_id == 'csrftoken':
continue
cart_goods = GoodsInfo.objects.get(id=goods_id)
cart_goods.goods_num = goods_num
cart_goods_list.append(cart_goods)
# 累加购物车商品总数
cart_goods_count = cart_goods_count + int(goods_num)
return render(request, 'goods.html', {'page_data': page_data,
'categories': categories,
'current_cag': current_cag,
'cart_goods_list': cart_goods_list,
'cart_goods_count': cart_goods_count,
'paginator': paginator,
'cag_id': cag_id})
首先获得当前的分类ID和当前的页码数据, 例如请求的网址为: locahost:8000/goods/?id=2&page=3, 则表示要查看分类id 为2, 页码为3的数据. "&"符号用于连接多个请求参数.
# 获得当前分类
cag_id = request.GET.get('cag', 1)
# 获得当前页码
page_id = request.GET.get('page', 1)
然后根据分类查询当前分类下所有的数据:
# 查询所有数据
goods_data = GoodsInfo.objects.filter(goods_cag_id=cag_id)
查完数据之后, 我们下面要对商品的数据进行分页. 首先导入分页器 Paginator, 该类能够帮我们完成分页操作.
from django.core.paginator import Paginator
该分页器对象的创建, 需要指定2个参数, 第一个是对那个结果集进行分页, 第二个参数指定每页显示多少条数据.
# 数据分页
paginator = Paginator(goods_data, 12)
# 获得当前页码数据
page_data = paginator.page(page_id)
创建完 paginator 对象之后, 我们通过其 page 方法即可获得当前页码指定的数据. page_data 为当前页码的数据. 下面介绍了该类的使用方法:
Paginator类
class Paginator(object_list,
per_page,
orphans=0,
allow_empty_first_page=True)
参数 | 描述 |
---|---|
object_list | 一个 list、tuple、Django QuerySet |
per_page | 每页显示多少条数据 |
orphans | 最后一页数据量大于orphans才显示最后一页 |
allow_empty_first_page | 如果False,那么数据集为空,会抛出EmptyPage异常 |
-
方法:
方法 | 描述 |
---|---|
Paginator.page(number) | 返回在提供的下标处的Page对象, 下标以1开始. 如果提供的页码不存在, 抛出 InvalidPage 异常. PageNotAnIntege r和 EmptyPage 是 InvalidPage 子类 |
-
属性:
属性 | 描述 |
---|---|
Paginator.num_pages | 页面的总数 |
Paginator.page_range | 页码的范围,从1开始,例如[1, 2, 3, 4] |
Paginator.count | 所有页面的对象总数 |
Page类
通常不需要手动构建 Page 对象, 我们可以从 Paginator.page() 来获得它们.
-
方法:
方法 | 描述 |
---|---|
Page.has_next() | 如果有下一页,则返回True |
Page.has_previous() | 如果有上一页,返回 True |
Page.has_other_pages() | 如果有上一页或下一页,返回True |
Page.next_page_number() | 返回下一页的页码. 如果下一页不存在, 抛出InvalidPage异常 |
Page.previous_page_number() | 返回上一页的页码。如果上一页不存在,抛出InvalidPage异常 |
-
属性:
属性 | 描述 |
---|---|
Page.number | 当前页的序号, 从1开始 |
下面的代码就是购物车数据的获取:
# 读取购物车商品列表
cart_goods_list = []
# 商品总数
cart_goods_count = 0
for goods_id, goods_num in request.COOKIES.items():
if goods_id == 'csrftoken':
continue
cart_goods = GoodsInfo.objects.get(id=goods_id)
cart_goods.goods_num = goods_num
cart_goods_list.append(cart_goods)
# 累加购物车商品总数
cart_goods_count = cart_goods_count + int(goods_num)
goods.html 模板代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>{{ current_cag.cag_name }}-商品列表</title>
<link rel="stylesheet" type="text/css" href="/static/css/reset.css">
<link rel="stylesheet" type="text/css" href="/static/css/main.css">
</head>
<body>
<div class="header_con">
<div class="header">
<div class="welcome fl">欢迎来到天天生鲜!</div>
</div>
</div>
<div class="search_bar clearfix">
<a href="/" class="logo fl"><img src="/static/images/logo.png"></a>
<div class="guest_cart fr">
<a href="/cart/show_cart/" class="cart_name fl">我的购物车</a>
<div class="goods_count fl">{{ cart_goods_count }}</div>
<ul class="cart_goods_show">
{% for cart_goods in cart_goods_list %}
<li>
<img src="/static/{{ cart_goods.goods_img }}" alt="商品图片">
<h4>{{ cart_goods.goods_name }}</h4>
<div>{{ cart_goods.goods_num }}</div>
</li>
{% endfor %}
</ul>
</div>
</div>
<div class="navbar_con">
<div class="navbar clearfix">
<div class="subnav_con fl">
<h1>全部商品分类</h1>
<span></span>
<ul class="subnav">
{% for cag in categories %}
<li><a href="?cag={{ cag.id }}&page=1" class="{{ cag.cag_css }}">{{ cag.cag_name }}</a></li>
{% endfor %}
</ul>
</div>
</div>
</div>
<div class="breadcrumb">
<a href="#">当前分类:</a>
<span></span>
<a href="#">{{ current_cag.cag_name }}</a>
</div>
<div class="main_wrap clearfix">
<div class="sort_bar"></div>
<ul class="goods_type_list clearfix">
{% for goods in page_data %}
<li>
<a href="/detail/?id={{ goods.id }}"><img src="/static/{{ goods.goods_img }}"></a>
<div class="operate">
<h4><a href="/detail/?id={{ goods.id }}">{{ goods.goods_name }}</a></h4>
<span class="prize">¥{{ goods.goods_price }}</span>
</div>
</li>
{% endfor %}
</ul>
<div class="pagenation">
{% if page_data.has_previous %}
<a href="?cag={{ cag_id }}&page={{ page_data.previous_page_number }}">上一页</a>
{% endif %}
{% for index in paginator.page_range %}
{% if index == page_data.number %}
<a href="?cag={{ cag_id }}&page={{ index }}" class="active">{{ index }}</a>
{% else %}
<a href="?cag={{ cag_id }}&page={{ index }}">{{ index }}</a>
{% endif %}
{% endfor %}
{% if page_data.has_next %}
<a href="?cag={{ cag_id }}&page={{ page_data.next_page_number }}">下一页></a>
{% endif %}
</div>
</div>
<div class="footer">
<div class="foot_link">
<a href="#">关于我们</a>
<span>|</span>
<a href="#">联系我们</a>
<span>|</span>
<a href="#">招聘人才</a>
<span>|</span>
<a href="#">友情链接</a>
</div>
<p>CopyRight © 2016 北京天天生鲜信息技术有限公司 All Rights Reserved</p>
<p>电话:010-****888 京ICP备*******8号</p>
</div>
</body>
</html>
如下代码用于显示购物车相关数据:
<a href="/cart/show_cart/" class="cart_name fl">我的购物车</a>
<div class="goods_count fl">{{ cart_goods_count }}</div>
<ul class="cart_goods_show">
{% for cart_goods in cart_goods_list %}
<li>
<img src="/static/{{ cart_goods.goods_img }}" alt="商品图片">
<h4>{{ cart_goods.goods_name }}</h4>
<div>{{ cart_goods.goods_num }}</div>
</li>
{% endfor %}
</ul>
如下代码用于显示商品分类数据:
{% for cag in categories %}
<li><a href="?cag={{ cag.id }}&page=1" class="{{ cag.cag_css }}">{{ cag.cag_name }}</a></li>
{% endfor %}
如下代码用于显示某分类下商品数据:
{% for goods in page_data %}
<li>
<a href="/detail/?id={{ goods.id }}"><img src="/static/{{ goods.goods_img }}"></a>
<div class="operate">
<h4><a href="/detail/?id={{ goods.id }}">{{ goods.goods_name }}</a></h4>
<span class="prize">¥{{ goods.goods_price }}</span>
</div>
</li>
{% endfor %}
如下代码显示分页页码:
{% if page_data.has_previous %}
<a href="?cag={{ cag_id }}&page={{ page_data.previous_page_number }}">上一页</a>
{% endif %}
{% for index in paginator.page_range %}
{% if index == page_data.number %}
<a href="?cag={{ cag_id }}&page={{ index }}" class="active">{{ index }}</a>
{% else %}
<a href="?cag={{ cag_id }}&page={{ index }}">{{ index }}</a>
{% endif %}
{% endfor %}
{% if page_data.has_next %}
<a href="?cag={{ cag_id }}&page={{ page_data.next_page_number }}">下一页></a>
{% endif %}
以上是关于新星计划Django基于PythonWeb的Django框架设计实现天天生鲜系统-8商品详细页面与商品分类功能实现的主要内容,如果未能解决你的问题,请参考以下文章
新星计划Django基于PythonWeb的Django框架设计实现天天生鲜系统-9购物车提交订单订单提交成功页面功能实现
Django基于PythonWeb的Django框架设计实现天天生鲜系统-7首页界面
Django基于PythonWeb的Django框架设计实现天天生鲜系统-1
Django基于PythonWeb的Django框架设计实现天天生鲜系统-2项目开发部署环境