新星计划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个参数:

  1. 当前分类是那个?

  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项目开发部署环境

Django基于PythonWeb的Django框架设计实现天天生鲜系统-5数据库操作

Django基于PythonWeb的Django框架设计实现天天生鲜系统-4创建视图