本规定对一个完整的开发过程按“软件过程改进方法和规范”把
产品生命周期
划分为 6 个阶段:
软件项目的过程有三大类: 项目管理过程
、项目研发过程
和机构支持过程
。
而这三类过程可以细分为19
个主要过程域,分布在PH0
到PH5
的各个阶段。
项目管理过程包6
个过程域,分为:立项管理
、结项管理
、项目规划
、项目监控
、风险管理
、需求管理
。
项目研发过程包8
个过程域,分为:需求开发
、技术预研
、系统设计
、实现与测试
、系统测试
、 Beta测试
、客户验收
、技术评审
。
机构支撑过程包5
个过程域,分为:配置管理
、质量保证
、培训管理
、外包与采购管理
、服务与维护
。
建议用户(企业)根据自身情况(如发 展战略、研发实力等)适当地修改使用
本商城项目分为网站前台和网站后台管理两部分:
根据转换算法,E-R 图中有 5 个实体类型,可以转换成 4 个关系模式:
1). 会员
(id号、账号、密码、真实姓名、性别、收货地址、邮政编码、电话、Email、状态、注册时间)
2). 商品类别
(类别id号,类别名称,父类别id,类别路径)
3). 商品
(商品id、类别id
、商品名称、生产厂家、详情描述、单价、图片名称、库存量、购买数量、点击次数、状态、添加时间)
4). 订单
(订单id号、会员id号
、联系人、收货地址、邮政编码、联系电话、购买时间、总金额、状态)
5). 订单详情
(id号、订单id号
、商品id号
,商品名称、单价、购买量)
-- 会员信息表(后台管理员信息也在此标准,通过状态区分)
CREATE TABLE `users`(
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL,
`name` varchar(16) DEFAULT NULL,
`password` char(32) NOT NULL,
`sex` tinyint(1) unsigned NOT NULL DEFAULT '1',
`address` varchar(255) DEFAULT NULL,
`code` char(6) DEFAULT NULL,
`phone` varchar(16) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`state` tinyint(1) unsigned NOT NULL DEFAULT '1',
`addtime` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 商品类别表
CREATE TABLE `type`(
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`pid` int(11) unsigned DEFAULT '0',
`path` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 商品信息表
CREATE TABLE `goods`(
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`typeid` int(11) unsigned NOT NULL,
`goods` varchar(32) NOT NULL,
`company` varchar(50) DEFAULT NULL,
`content` text,
`price` double(6,2) unsigned NOT NULL,
`picname` varchar(255) DEFAULT NULL,
`store` int(11) unsigned NOT NULL DEFAULT '0',
`num` int(11) unsigned NOT NULL DEFAULT '0',
`clicknum` int(11) unsigned NOT NULL DEFAULT '0',
`state` tinyint(1) unsigned NOT NULL DEFAULT '1',
`addtime` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `typeid` (`typeid`)
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 订单信息表
CREATE TABLE `orders`(
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`uid` int(11) unsigned DEFAULT NULL,
`linkman` varchar(32) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`code` char(6) DEFAULT NULL,
`phone` varchar(16) DEFAULT NULL,
`addtime` datetime DEFAULT NULL,
`total` double(8,2) unsigned DEFAULT NULL,
`state` tinyint(1) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 订单信息详情表
CREATE TABLE `detail`(
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`orderid` int(11) unsigned DEFAULT NULL,
`goodsid` int(11) unsigned DEFAULT NULL,
`name` varchar(32) DEFAULT NULL,
`price` double(6,2) DEFAULT NULL,
`num` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 在user上表中添加一条后台管理员账户数据
insert into users values(null,'admin','管理员',md5('admin'),1,'北京市朝阳区大山子007号','100086','13566686868','122794105@qq.com',0,now())
域约束
、实体完整性约束
和关联完整性约束
。本次项目共计四个应用:
myadmin
、
web
、
common
和
ueditor
/myobject/
├── manage.py
├── myobject
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── common 公共应用
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── shopmiddleware.py 自定义的中间件
│ ├── migrations
│ ├── models.py 网站前后台的共用Model类
│ ├── tests.py
│ └── views.py
├── myadmin 网站后台应用
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ ├── views
│ │ ├── index.py 后台主视图
│ │ ├── users.py 会员管理视图
│ │ ├── type.py 商品类别管理视图
│ │ ├── goods.py 商品管理视图
│ │ └── orders.py 订单管理视图
│ ├── models.py
│ ├── tests.py
│ └── urls.py
│
├── web 网站前台应用
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ ├── views
│ │ ├── index.py web前台主视图
│ │ ├── users.py 会员操作视图
│ │ ├── cart.py 购物车管理视图
│ │ └── orders.py 订单处理视图
│ ├── models.py
│ ├── tests.py
│ └── urls.py
│
├── ueditor 百度编辑器(富文本编辑器)
│ ├── __init__.py
│ ├── UE
│ ├── controller.py
│ ├── msyhdb.ttf
│ ├── ueconfig.json
│ └── urls.py
│
├── templates 模板目录
│ ├── myadmin 后台模板总目录
│ │ ├── users/ 后台会员管理
│ │ │ ├── index.html
│ │ │ ├── add.html
│ │ │ ├── edit.html
│ │ │ ├── repass.html
│ │ ├── type/ 后台类别管理模板
│ │ │ ├── index.html
│ │ │ ├── add.html
│ │ │ ├── edit.html
│ │ ├── goods/ 商品信息管理模板
│ │ │ ├── index.html
│ │ │ ├── add.html
│ │ │ ├── edit.html
│ │ ├── orders/ 订单信息管理模板
│ │ │ ├── index.html
│ │ │ ├── edit.html
│ │ ├── index.html
│ │ ├── login.html
│ │ ├── base.html
│ │ ├── info.html
│ │
│ ├── web 前台模板目录
│ │ ├── base.html
│ │ ├── index.html
│ │ ├── list.html
│ │ ├── detail.html
│ │ ├── login.html
│ │ ├── signup.html
│ │ └── ......
│
├── static 静态资源目录
│ ├── myadmin 后台静态资源
│ │ ├──....
│ │ ├──....
│ │
│ │
│ ├── web 网站前台静态资源
│ │ ├──....
│ │ ├──....
模块 | 操作 | 权限 |
---|---|---|
登录&退出管理 | 获取登录界面、处理登录、退出、验证码 | 无 |
后台首页页 | 后台首页 | 网站编辑权限 |
后台会员信息管理 | 浏览(搜索&分页)、详情、更改状态、重置密码 | 网站编辑权限 |
商品类别管理 | 浏览、获取添加界面、执行添加、获取编辑界面、执行修改、删除 | 网站编辑权限 |
商品信息管理 | 浏览(搜索&分页)、获取添加界面、执行添加、获取编辑界面、执行修改、删除 | 网站编辑权限 |
订单信息管理 | 浏览(搜索&分页)、查看订单详情、处理订单、删除 | 网站编辑权限 |
模块 | 操作 | 权限 |
---|---|---|
商品展示 | 商品首页展示、列表页(搜索分页)、商品详情页 | 无 |
购物车管理 | 添加商品、查看购物车,修改、删除、清空 | 无 |
前台会员管理 | 注册界面、执行注册,登录界面,执行登录,验证码、退出 | 无 |
订单处理 | 订单处理界面,确认订单界面、执行订单处理 | 会员权限 |
会员中心管理 | 个人信息界面、执行个人信息修改,查看订单,订单详情、处理订单 | 会员权限 |
建议统一URL访问格式:
http://主机名:端口/应用名/视图名/函数名
其中:index省略不写,web前台应用名省略不写。
视图中的函数命名格式:
遵循良好的编码风格,可以有效的提高代码的可读性,降低出错几率和维护难度。
在团队开发中,使用(尽量)统一的编码风格,还可以降低沟通成本。
网上有很多版本的编码规范介绍,基本上都是遵循 PEP8 的规范:
具体详见:https://www.python.org/dev/peps/pep-0008/
如下参考格式:
缩进
* 不要使用 tab 缩进
* 使用任何编辑器写 Python,请把一个 tab 展开为 4 个空格
* 绝对不要混用 tab 和空格,否则容易出现 IndentationError
空格
* 在 list, dict, tuple, set, 参数列表的 , 后面加一个空格
* 在 dict 的 : 后面加一个空格
* 在注释符号 # 后面加一个空格,但是 #!/usr/bin/python 的 # 后不能有空格
* 操作符两端加一个空格,如 +, -, *, /, |, &, =
* 接上一条,在参数列表里的 = 两端不需要空格
* 括号((), {}, [])内的两端不需要空格
空行
* function 和 class 顶上两个空行
* class 的 method 之间一个空行
* 函数内逻辑无关的段落之间空一行,不要过度使用空行
* 不要把多个语句写在一行,然后用 ; 隔开
* if/for/while 语句中,即使执行语句只有一句,也要另起一行
换行
* 每一行代码控制在 80 字符以内
* 使用 \ 或 () 控制换行.
命名
* 使用有意义的,英文单词或词组,绝对不要使用汉语拼音
* package/module 名中不要出现 -
import
* 所有 import 尽量放在文件开头,在 docstring 下面,其他变量定义的上面
* 不要使用 from foo imort *
* import 需要分组,每组之间一个空行,每个分组内的顺序尽量采用字典序,分组顺序是:
* 标准库
* 第三方库
* 本项目的 package 和 module
注释
* 文档字符串 docstring, 是 package, module, class, method, function 级别的注释,可以通过 * __doc__ 成员访问到,注释内容在一对 """ 符号之间
* function, method 的文档字符串应当描述其功能、输入参数、返回值,如果有复杂的算法和实现,也需要写清楚
不要写错误的注释,不要无谓的注释
异常
* 不要轻易使用 try/except
* except 后面需要指定捕捉的异常,裸露的 except 会捕捉所有异常,意味着会隐藏潜在的问题
* 可以有多个 except 语句,捕捉多种异常,分别做异常处理
* 使用 finally 子句来处理一些收尾操作
* try/except 里的内容不要太多,只在可能抛出异常的地方使用,
shopdb
shopdb
数据库中myobject
框架和应用 myamdin
、web
和common
。 # 创建项目框架 `myobject`
$ django-admin startproject myobject
$ cd myobject
# 在项目中创建一个myadmin应用(项目的后台管理)
$ python manage.py startapp myadmin
# 在项目中再创建一个web应用(项目前台)
$ python manage.py startapp web
# 在项目中再创建一个common应用(项目的前台和后台的公告应用)
$ python manage.py startapp common
# 创建模板目录
$ mkdir templates
$ mkdir templates/myadmin
$ mkdir templates/web
# 创建静态资源目录
$ mkdir static
$ mkdir static/myadmin
$ mkdir static/web
# 创建前后台应用模板目录,并在里面各创建一个`__init__.py`和`index.py`的空文件
$ mkdir myadmin/views
$ touch myadmin/views/__init__.py
$ touch myadmin/views/index.py
$ mkdir web/views
$ touch web/views/__init__.py
$ touch web/views/index.py
# 删除前后台应用的默认模板文件
# rm -rf myadmin/views.py
# rm -rf web/views.py
# 拷贝路由文件到应用目录中
$ cp myobject/urls.py myadmin/urls.py
$ cp myobject/urls.py web/urls.py
# 退出项目目录
$ cd ..
#查看项目目录结构
$ tree myobject
myobject/
├── manage.py
├── myobject
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── myadmin
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── views
│ │ ├── __init__.py
│ │ └── index.py
│ ├── models.py
│ ├── tests.py
│ └── urls.py
├── web
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ ├── views
│ │ ├── __init__.py
│ │ └── index.py
│ ├── models.py
│ ├── tests.py
│ └── urls.py
├── common
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── static
│ ├── myadmin/
│ └── web/
└── templates
├── myadmin/
└── web/
myobject/myobject/__init__.py
文件,添加Pymysql的数据库操作支持import pymysql
pymysql.install_as_MySQLdb()
注意:此配置需要安装pymysql软件包, 如:$ pip install pymysql
# myobject/myobject/settings.py 项目配置文件
# 1. 配置允许访问的主机名信息
ALLOWED_HOSTS = ['*']
或
ALLOWED_HOSTS = ['localhost','127.0.0.1','192.168.2.240']
...
# 2. 将myadmin和web的应用添加到项目框架结构中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myadmin',
'web',
'common',
]
...
# 3. 配置模板目录 os.path.join(BASE_DIR,'templates')
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
...
# 4. 配置项目的数据库连接信息:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'shopdb',
'USER': 'root',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '3306',
}
}
...
# 5. 设置时区和语言
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
...
# 6. 配置网站的静态资源目录
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
# myobject/myobject/urls.py
from django.conf.urls import url,include
#from django.contrib import admin
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^myadmin/', include('myadmin.urls')), #网站后台路由
url(r'^', include('web.urls')), #网站前台路由
]
# myobject/myadmin/urls.py
from django.conf.urls import url
from myadmin.views import index
urlpatterns = [
# 后台首页
url(r'^$', index.index, name="myadmin_index"),
]
# myobject/web/urls.py
from django.conf.urls import url
from web.views import index
urlpatterns = [
# url(r'^$', index.index, name="index"),
]
# myobject/myadmin/views/index.py
from django.shortcuts import render
from django.http import HttpResponse
#后台首页
def index(request):
return HttpResponse('欢迎进入商城网站后台!')
# myobject/web/views/index.py
from django.shortcuts import render
from django.http import HttpResponse
#前台首页
def index(request):
return HttpResponse('欢迎进入商城网站前台首页!')
[root@localhost myobject]# pwd
/python/myobject
[root@localhost myobject]# ls
manage.py myadmin myobject web static templates
[root@localhost myobject]# python3 manage.py runserver 0:8000
Performing system checks...
System check identified no issues (0 silenced).
April 06, 2018 - 14:29:36
Django version 1.11, using settings 'myobject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
^C[root@localhost myobject]#
6.1. 使用事先准备好的后台模板:
从github上下载一个后台简洁模板:https://github.com/alecfan/mstp_17_akira
将后台模板目录中的资源目录:css
、js
、img
复制到项目的后台静态资源目录static/myadmin/
中
在templates/myadmin/
目录中创建一个基类父模板文件base.html
在templates/myadmin/
目录中创建一个首页模板文件index.html
在templates/myadmin/
目录中创建一个信息提示模板文件info.html
修改
myobject/myadmin/views/index.py
视图文件中index函数中代码:
def index(request):
'''管理后台首页'''
return render(request,"myadmin/index.html")
6.2. 编辑父类模板:/templates/myadmin/base.html
{% load static from staticfiles %}
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="utf-8">
<title>网站后台管理</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{% static 'myadmin/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'myadmin/css/bootstrap-responsive.min.css' %}" rel="stylesheet">
<link href="{% static 'myadmin/css/site.css' %}" rel="stylesheet">
<!--[if lt IE 9]><script src="{% static 'myadmin/js/html5.js' %}"></script><![endif]-->
</head>
<body>
<div class="container">
<!-- 页头开始 -->
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a> <a class="brand" href="#">网站后台管理</a>
<div class="nav-collapse">
<ul class="nav">
<li class="active">
<a href="index.html">首页</a>
</li>
<li>
<a href="settings.htm">在线设置</a>
</li>
<li>
<a href="help.htm">帮助</a>
</li>
<li class="dropdown">
<a href="help.htm" class="dropdown-toggle" data-toggle="dropdown">更多 <b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="help.htm">Introduction Tour</a>
</li>
<li>
<a href="help.htm">Project Organisation</a>
</li>
<li>
<a href="help.htm">Task Assignment</a>
</li>
<li>
<a href="help.htm">Access Permissions</a>
</li>
<li class="divider">
</li>
<li class="nav-header">
Files
</li>
<li>
<a href="help.htm">How to upload multiple files</a>
</li>
<li>
<a href="help.htm">Using file version</a>
</li>
</ul>
</li>
</ul>
<form class="navbar-search pull-left" action="">
<input type="text" class="search-query span2" placeholder="Search" />
</form>
<ul class="nav pull-right">
<li>
<a href="profile.htm">@管理员</a>
</li>
<li>
<a href="login.htm">退出</a>
</li>
</ul>
</div>
</div>
</div>
</div><!-- 页头结束-->
<div class="row">
<div class="span3">
<!-- 侧边导航开始 -->
<div class="well" style="padding: 8px 0;">
<ul class="nav nav-list">
<li class="nav-header">
导航栏
</li>
<li class="active">
<a href="index.htm"><i class="icon-white icon-home"></i> 首页</a>
</li>
<li class="nav-header">
会员管理
</li>
<li>
<a href="#"><i class="icon-folder-open"></i> 浏览会员</a>
</li>
<li>
<a href="#"><i class="icon-check"></i> 添加会员</a>
</li>
<li class="nav-header">
商品类别管理
</li>
<li>
<a href="messages.htm"><i class="icon-envelope"></i> 浏览商品类别</a>
</li>
<li>
<a href="files.htm"><i class="icon-file"></i> 添加商品类别</a>
</li>
<li class="nav-header">
商品信息管理
</li>
<li>
<a href="activity.htm"><i class="icon-list-alt"></i> 浏览商品信息</a>
</li>
<li>
<a href="activity.htm"><i class="icon-list-alt"></i> 添加商品信息</a>
</li>
<li class="divider">
</li>
<li>
<a href="help.htm"><i class="icon-info-sign"></i> Help</a>
</li>
<li class="nav-header">
Bonus Templates
</li>
<li>
<a href="gallery.htm"><i class="icon-picture"></i> Gallery</a>
</li>
<li>
<a href="blank.htm"><i class="icon-stop"></i> Blank Slate</a>
</li>
</ul>
</div><!-- 侧边导航结束 -->
</div>
<div class="span9">
<!-- 主体开始 -->
{% block mainbody %}
{% endblock %}
<!-- 主体结束 -->
</div>
</div>
</div>
<script src="{% static 'myadmin/js/jquery.min.js' %}"></script>
<script src="{% static 'myadmin/js/bootstrap.min.js' %}"></script>
<script src="{% static 'myadmin/js/site.js' %}"></script>
</body>
</html>
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h2>
商城网站后台管理首页
</h2>
<div class="hero-unit">
<h3>
Welcome!
</h3>
<p>
To get the most out of Akira start with our 3 minute tour.
</p>
<p>
<a href="help.htm" class="btn btn-primary btn-large">Start Tour</a> <a class="btn btn-large">No Thanks</a>
</p>
</div>
<div class="well summary">
<ul>
<li>
<a href="#"><span class="count">3</span> Projects</a>
</li>
<li>
<a href="#"><span class="count">27</span> Tasks</a>
</li>
<li>
<a href="#"><span class="count">7</span> Messages</a>
</li>
<li class="last">
<a href="#"><span class="count">5</span> Files</a>
</li>
</ul>
</div>
{% endblock %}
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h2>
操作信息提示
</h2>
<h4>
{{ info }}
</h4>
{% endblock %}
shopdb
中创建users表,若此表已存在请跳过CREATE TABLE `users`(
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL,
`name` varchar(16) DEFAULT NULL,
`password` char(32) NOT NULL,
`sex` tinyint(1) unsigned NOT NULL DEFAULT '1',
`address` varchar(255) DEFAULT NULL,
`code` char(6) DEFAULT NULL,
`phone` varchar(16) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`state` tinyint(1) unsigned NOT NULL DEFAULT '1',
`addtime` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
)ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
common
应用目录中编辑:myobject/common/models.py
模型文件from django.db import models
from datetime import datetime
#用户信息模型
class Users(models.Model):
username = models.CharField(max_length=32)
name = models.CharField(max_length=16)
password = models.CharField(max_length=32)
sex = models.IntegerField(default=1)
address = models.CharField(max_length=255)
code = models.CharField(max_length=6)
phone = models.CharField(max_length=16)
email = models.CharField(max_length=50)
state = models.IntegerField(default=1)
addtime = models.DateTimeField(default=datetime.now)
def toDict(self):
return {'id':self.id,'username':self.username,'name':self.name,'password':self.password,'address':self.address,'phone':self.phone,'email':self.email,'state':self.state,'addtime':self.addtime}
class Meta:
db_table = "users" # 更改表名
from django.conf.urls import url
from myadmin.views import index,users
urlpatterns = [
# 后台首页
url(r'^$', index.index, name="myadmin_index"),
# 后台用户管理
url(r'^users$', users.index, name="myadmin_users_index"),
url(r'^users/add$', users.add, name="myadmin_users_add"),
url(r'^users/insert$', users.insert, name="myadmin_users_insert"),
url(r'^users/del/(?P<uid>[0-9]+)$', users.delete, name="myadmin_users_del"),
url(r'^users/edit/(?P<uid>[0-9]+)$', users.edit, name="myadmin_users_edit"),
url(r'^users/update/(?P<uid>[0-9]+)$', users.update, name="myadmin_users_update"),
]
from django.shortcuts import render
from django.http import HttpResponse
from common.models import Users
from datetime import datetime
# 浏览会员
def index(request):
# 执行数据查询,并放置到模板中
list = Users.objects.all()
context = {"userslist":list}
#return HttpResponse(list)
return render(request,'myadmin/users/index.html',context)
# 会员信息添加表单
def add(request):
return render(request,'myadmin/users/add.html')
#执行会员信息添加
def insert(request):
try:
ob = Users()
ob.username = request.POST['username']
ob.name = request.POST['name']
#获取密码并md5
import hashlib
m = hashlib.md5()
m.update(bytes(request.POST['password'],encoding="utf8"))
ob.password = m.hexdigest()
ob.sex = request.POST['sex']
ob.address = request.POST['address']
ob.code = request.POST['code']
ob.phone = request.POST['phone']
ob.email = request.POST['email']
ob.state = 1
ob.addtime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
ob.save()
context = {'info':'添加成功!'}
except Exception as err:
print(err)
context = {'info':'添加失败!'}
return render(request,"myadmin/info.html",context)
# 执行会员信息删除
def delete(request,uid):
try:
ob = Users.objects.get(id=uid)
ob.delete()
context = {'info':'删除成功!'}
except:
context = {'info':'删除失败!'}
return render(request,"myadmin/info.html",context)
# 打开会员信息编辑表单
def edit(request,uid):
try:
ob = Users.objects.get(id=uid)
context = {'user':ob}
return render(request,"myadmin/users/edit.html",context)
except Exception as err:
print(err)
context = {'info':'没有找到要修改的信息!'}
return render(request,"myadmin/info.html",context)
# 执行会员信息编辑
def update(request,uid):
try:
ob = Users.objects.get(id=uid)
ob.name = request.POST['name']
ob.sex = request.POST['sex']
ob.address = request.POST['address']
ob.code = request.POST['code']
ob.phone = request.POST['phone']
ob.email = request.POST['email']
ob.state = request.POST['state']
ob.save()
context = {'info':'修改成功!'}
except Exception as err:
print(err)
context = {'info':'修改失败!'}
return render(request,"myadmin/info.html",context)
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h4>
会员信息管理
</h4>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>账号</th>
<th>真实姓名</th>
<th>性别</th>
<th>邮箱</th>
<th>注册时间</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for vo in userslist %}
<tr>
<td>{{ vo.username }}</td>
<td>{{ vo.name }}</td>
<td>{% if vo.sex == 1 %}男{% else %}女{% endif %}</td>
<td>{{ vo.email }}</td>
<td>{{ vo.addtime|date:'Y-m-d H:i:s' }}</td>
<td>{{ vo.state }}</td>
<td>
<a href="{% url 'myadmin_users_del' vo.id %}" class="view-link">删除</a>
<a href="{% url 'myadmin_users_edit' vo.id %}" class="view-link">编辑</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<ul>
<li class="disabled">
<a href="#">«</a>
</li>
<li class="active">
<a href="#">1</a>
</li>
<li>
<a href="#">2</a>
</li>
<li>
<a href="#">3</a>
</li>
<li>
<a href="#">4</a>
</li>
<li>
<a href="#">»</a>
</li>
</ul>
</div>
{% endblock %}
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h3>
会员信息管理
</h3>
<form id="edit-profile" action="{% url 'myadmin_users_insert' %}" class="form-horizontal" method="post">
{% csrf_token %}
<fieldset>
<legend>添加会员信息</legend>
<div class="control-group">
<label class="control-label" for="input01">账号:</label>
<div class="controls">
<input type="text" name="username" class="input-xlarge" id="input01" value="" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">密码:</label>
<div class="controls">
<input type="password" name="password" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">重复密码:</label>
<div class="controls">
<input type="password" name="repassword" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">真实姓名:</label>
<div class="controls">
<input type="text" name="name" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">性别:</label>
<div class="controls">
<input type="radio" name="sex" class="input-xlarge" id="input01" value="1" /> 男
<input type="radio" name="sex" class="input-xlarge" id="input01" value="0" /> 女
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">地址:</label>
<div class="controls">
<input type="text" name="address" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">邮编:</label>
<div class="controls">
<input type="text" name="code" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">电话:</label>
<div class="controls">
<input type="text" name="phone" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">email邮箱:</label>
<div class="controls">
<input type="text" name="email" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">添加</button> <button type="reset" class="btn">重置</button>
</div>
</fieldset>
</form>
{% endblock %}
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h3>
会员信息管理
</h3>
<form id="edit-profile" action="{% url 'myadmin_users_update' user.id %}" class="form-horizontal" method="post">
{% csrf_token %}
<fieldset>
<legend>编辑会员信息</legend>
<div class="control-group">
<label class="control-label" for="input01">账号:</label>
<div class="controls">
{{ user.username }}
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">真实姓名:</label>
<div class="controls">
<input type="text" name="name" class="input-xlarge" id="input01" value="{{ user.name }}" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">性别:</label>
<div class="controls">
<input type="radio" name="sex" class="input-xlarge" id="input01" value="1"
{% if user.sex == 1 %}checked{% endif %} /> 男
<input type="radio" name="sex" class="input-xlarge" id="input01" value="0"
{% if user.sex == 0 %}checked{% endif %} /> 女
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">地址:</label>
<div class="controls">
<input type="text" name="address" class="input-xlarge" id="input01" value="{{ user.address }}" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">邮编:</label>
<div class="controls">
<input type="text" name="code" class="input-xlarge" id="input01" value="{{ user.code }}" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">电话:</label>
<div class="controls">
<input type="text" name="phone" class="input-xlarge" id="input01" value="{{ user.phone }}" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">email邮箱:</label>
<div class="controls">
<input type="text" name="email" class="input-xlarge" id="input01" value="{{ user.email }}" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">状态:</label>
<div class="controls">
<input type="radio" name="state" class="input-xlarge" id="input01" value="0"
{% if user.state == 0 %}checked{% endif %} /> 管理员
<input type="radio" name="state" class="input-xlarge" id="input01" value="1"
{% if user.state == 1 %}checked{% endif %} /> 启用会员
<input type="radio" name="state" class="input-xlarge" id="input01" value="2"
{% if user.state == 2 %}checked{% endif %} /> 禁用用户
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">保存</button> <button type="reset" class="btn">重置</button>
</div>
</fieldset>
</form>
{% endblock %}
[root@localhost myobject]# pwd
/python/myobject
[root@localhost myobject]# ls
manage.py myadmin myobject myweb static templates
[root@localhost myobject]# python3 manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
April 06, 2018 - 14:29:36
Django version 1.11, using settings 'myobject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
^C[root@localhost myobject]#
注意:本节实战会使用到Django框架中的session,而session信息又存放的数据库中,所以要先使用数据迁移命令在MySQL数据库中先生成一些Django默认自带表。
python manage.py migrate
myobject/common/shopmiddleware.py
, 代码如下:# 自定义中间件类
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
import re
class ShopMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization(一次性配置和初始化).
#print("ShopMiddleware")
def __call__(self, request):
# 定义网站后台不用登录也可访问的路由url
urllist = ['/myadmin/login','/myadmin/dologin','/myadmin/logout']
# 获取当前请求路径
path = request.path
#print("Hello World!"+path)
# 判断当前请求是否是访问网站后台,并且path不在urllist中
if re.match("/myadmin",path) and (path not in urllist):
# 判断当前用户是否没有登录
if "adminuser" not in request.session:
# 执行登录界面跳转
return redirect(reverse('myadmin_login'))
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
myobject/settings.py
配置文件, 添加如下代码...
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'common.shopmiddleware.ShopMiddleware', #注册中间件
]
...
myobject/myadmin/urls.py
加入如下代码 ....
# 后台管理员路由
url(r'^login$', index.login, name="myadmin_login"),
url(r'^dologin$', index.dologin, name="myadmin_dologin"),
url(r'^logout$', index.logout, name="myadmin_logout"),
....
myobject/myadmin/views/index.py
文件 并加入如下代码:...
# ==============后台管理员操作====================
# 会员登录表单
def login(request):
return render(request,'myadmin/login.html')
# 会员执行登录
def dologin(request):
pass
# 会员退出
def logout(request):
pass
...
templates/myadmin/login.html
代码如下:{% load static from staticfiles %}
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="utf-8">
<title>Login - Akira</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{% static 'myadmin/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'myadmin/css/bootstrap-responsive.min.css' %}" rel="stylesheet">
<link href="{% static 'myadmin/css/site.css' %}" rel="stylesheet">
<!--[if lt IE 9]><script src="{% static 'myadmin/js/html5.js' %}"></script><![endif]-->
</head>
<body>
<div id="login-page" class="container">
<h1>商城后台管理登录</h1>
<form id="login-form" method="post" class="well" action="{% url 'myadmin_dologin' %}">
{% csrf_token %}
账号:<input type="text" name="username" class="span2" placeholder="输入账号" /><br />
密码:<input type="password" name="password" class="span2" placeholder="输入密码" /><br />
<label class="checkbox"> <input type="checkbox" /> Remember me </label>
<button type="submit" class="btn btn-primary">登录</button>
<button type="reset" class="btn">重置</button>
</form>
<br/>
<span style="color:red">{{ info }}</span>
</div>
<script src="{% static 'myadmin/js/jquery.min.js' %}"></script>
<script src="{% static 'myadmin/js/bootstrap.min.js' %}"></script>
<script src="{% static 'myadmin/js/site.js' %}"></script>
</body>
</html>
myobject/myadmin/urls.py
加入如下代码 ....
# 后台管理员路由
url(r'^login$', index.login, name="myadmin_login"),
url(r'^dologin$', index.dologin, name="myadmin_dologin"),
url(r'^logout$', index.logout, name="myadmin_logout"),
....
myobject/myadmin/views/index.py
文件 并加入如下代码:from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from common.models import Users
import time,json
...
# ==============后台管理员操作====================
# 会员登录表单
def login(request):
return render(request,'myadmin/login.html')
# 会员执行登录
def dologin(request):
try:
#根据账号获取登录者信息
user = Users.objects.get(username=request.POST['username'])
#判断当前用户是否是后台管理员用户
if user.state == 0:
# 验证密码
import hashlib
m = hashlib.md5()
m.update(bytes(request.POST['password'],encoding="utf8"))
if user.password == m.hexdigest():
# 此处登录成功,将当前登录信息放入到session中,并跳转页面
request.session['adminuser'] = user.name
#print(json.dumps(user))
return redirect(reverse('myadmin_index'))
else:
context = {'info':'登录密码错误!'}
else:
context = {'info':'此用户非后台管理用户!'}
except:
context = {'info':'登录账号错误!'}
return render(request,"myadmin/login.html",context)
# 会员退出
def logout(request):
# 清除登录的session信息
del request.session['adminuser']
# 跳转登录页面(url地址改变)
return redirect(reverse('myadmin_login'))
# 加载登录页面(url地址不变)
#return render(request,"myadmin/login.html")
...
templates/myadmin/login.html
代码如下:{% load static from staticfiles %}
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="utf-8">
<title>Login - Akira</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{% static 'myadmin/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'myadmin/css/bootstrap-responsive.min.css' %}" rel="stylesheet">
<link href="{% static 'myadmin/css/site.css' %}" rel="stylesheet">
<!--[if lt IE 9]><script src="{% static 'myadmin/js/html5.js' %}"></script><![endif]-->
</head>
<body>
<div id="login-page" class="container">
<h1>商城后台管理登录</h1>
<form id="login-form" method="post" class="well" action="{% url 'myadmin_dologin' %}">
{% csrf_token %}
账号:<input type="text" name="username" class="span2" placeholder="输入账号" /><br />
密码:<input type="password" name="password" class="span2" placeholder="输入密码" /><br />
<label class="checkbox"> <input type="checkbox" /> Remember me </label>
<button type="submit" class="btn btn-primary">登录</button>
<button type="reset" class="btn">重置</button>
</form>
<br/>
<span style="color:red">{{ info }}</span>
</div>
<script src="{% static 'myadmin/js/jquery.min.js' %}"></script>
<script src="{% static 'myadmin/js/bootstrap.min.js' %}"></script>
<script src="{% static 'myadmin/js/site.js' %}"></script>
</body>
</html>
templates/myadmin/base.html
代码如下:...
<ul class="nav pull-right">
<li>
<a href="profile.htm">@{{ request.session.adminuser }}</a>
</li>
<li>
<a href="{% url 'myadmin_logout' %}">退出</a>
</li>
</ul>
...
myobject/myadmin/urls.py
加入如下代码 ....
# 后台管理员路由
url(r'^login$', index.login, name="myadmin_login"),
url(r'^dologin$', index.dologin, name="myadmin_dologin"),
url(r'^logout$', index.logout, name="myadmin_logout"),
url(r'^verify$', index.verify, name="myadmin_verify"), #验证码
....
myobject/myadmin/views/index.py
文件 并加入如下代码:后台管理员操作
中添加输出验证码方法 verify()
STXIHEI.TTF
复制到 static/目录下...
# ==============后台管理员操作====================
# 会员登录表单
def verify(request):
#引入随机函数模块
import random
from PIL import Image, ImageDraw, ImageFont
#定义变量,用于画面的背景色、宽、高
#bgcolor = (random.randrange(20, 100), random.randrange(
# 20, 100),100)
bgcolor = (242,164,247)
width = 100
height = 25
#创建画面对象
im = Image.new('RGB', (width, height), bgcolor)
#创建画笔对象
draw = ImageDraw.Draw(im)
#调用画笔的point()函数绘制噪点
for i in range(0, 100):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
draw.point(xy, fill=fill)
#定义验证码的备选值
str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
#随机选取4个值作为验证码
rand_str = ''
for i in range(0, 4):
rand_str += str1[random.randrange(0, len(str1))]
#构造字体对象,ubuntu的字体路径为“/usr/share/fonts/truetype/freefont”
font = ImageFont.truetype('static/STXIHEI.TTF', 21)
#font = ImageFont.load_default().font
#构造字体颜色
fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
#绘制4个字
draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
#释放画笔
del draw
#存入session,用于做进一步验证
request.session['verifycode'] = rand_str
"""
python2的为
# 内存文件操作
import cStringIO
buf = cStringIO.StringIO()
"""
# 内存文件操作-->此方法为python3的
import io
buf = io.BytesIO()
#将图片保存在内存中,文件类型为png
im.save(buf, 'png')
#将内存中的图片数据返回给客户端,MIME类型为图片png
return HttpResponse(buf.getvalue(), 'image/png')
...
__call__()
方法的 urllist
变量中加入:/myadmin/verify
# 定义网站后台不用登录也可访问的路由url
urllist = ['/myadmin/login','/myadmin/dologin','/myadmin/logout','/myadmin/verify']
测试:http://localhost:8000/myadmin/verify
templates/myadmin/login.html
中加入代码如下:....
<form id="login-form" method="post" class="well" action="{% url 'myadmin_dologin' %}">
{% csrf_token %}
账 号:<input type="text" name="username" class="span2" placeholder="输入账号" /><br />
密 码:<input type="password" name="password" class="span2" placeholder="输入密码" /><br />
验证码:<input type="text" name="code" class="span2" style="width:30px;" />
<img src="{% url 'myadmin_verify'%}" onclick="this.src='{% url 'myadmin_verify' %}?sn='+Math.random()"/>
<br />
<label class="checkbox"> <input type="checkbox" /> Remember me </label>
<button type="submit" class="btn btn-primary">登录</button>
<button type="reset" class="btn">重置</button>
</form>
...
myobject/myadmin/views/index.py
文件dologin()
中加入验证代码...
# 会员执行登录
def dologin(request):
# 校验验证码
verifycode = request.session['verifycode']
code = request.POST['code']
if verifycode != code:
context = {'info':'验证码错误!'}
return render(request,"myadmin/login.html",context)
try:
#根据账号获取登录者信息
user = Users.objects.get(username=request.POST['username'])
#判断当前用户是否是后台管理员用户
if user.state == 0:
# 验证密码
import hashlib
m = hashlib.md5()
m.update(bytes(request.POST['password'],encoding="utf8"))
if user.password == m.hexdigest():
# 此处登录成功,将当前登录信息放入到session中,并跳转页面
request.session['adminuser'] = user.name
#print(json.dumps(user))
return redirect(reverse('myadmin_index'))
else:
context = {'info':'登录密码错误!'}
else:
context = {'info':'此用户非后台管理用户!'}
except:
context = {'info':'登录账号错误!'}
return render(request,"myadmin/login.html",context)
....
本页面完成项目后台管理的商品类别信息模块操作
type
shopdb
中创建type表,若此表已存在请跳过CREATE TABLE `type` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`pid` int(11) unsigned DEFAULT '0',
`path` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
common
应用目录中编辑:myobject/common/models.py
模型文件from django.db import models
#商品类别信息模型
class Types(models.Model):
name = models.CharField(max_length=32)
pid = models.IntegerField(default=0)
path = models.CharField(max_length=255)
class Meta:
db_table = "type" # 更改表名
from django.conf.urls import url
from myadmin.views import index,users,type
urlpatterns = [
...
# 后台商品类别信息管理
url(r'^type$', type.index, name="myadmin_type_index"),
url(r'^type/add/(?P<tid>[0-9]+)$', type.add, name="myadmin_type_add"),
url(r'^type/insert$', type.insert, name="myadmin_type_insert"),
url(r'^type/del/(?P<tid>[0-9]+)$', type.delete, name="myadmin_type_del"),
url(r'^type/edit/(?P<tid>[0-9]+)$', type.edit, name="myadmin_type_edit"),
url(r'^type/update/(?P<tid>[0-9]+)$', type.update, name="myadmin_type_update"),
]
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from common.models import Types
# 浏览商品类别信息
def index(request):
# 执行数据查询,并放置到模板中
list = Types.objects.extra(select = {'_has':'concat(path,id)'}).order_by('_has')
# 遍历查询结果,为每个结果对象追加一个pname属性,目的用于缩进标题
for ob in list:
ob.pname ='. . . '*(ob.path.count(',')-1)
# print(list[0].__dict__)
context = {"typeslist":list}
return render(request,'myadmin/type/index.html',context)
# 商品类别信息添加表单
def add(request,tid):
# 获取父类别信息,若没有则默认为根类别信息
if tid == '0':
context = {'pid':0,'path':'0,','name':'根类别'}
else:
ob = Types.objects.get(id=tid)
context = {'pid':ob.id,'path':ob.path+str(ob.id)+',','name':ob.name}
return render(request,'myadmin/type/add.html',context)
#执行商品类别信息添加
def insert(request):
try:
ob = Types()
ob.name = request.POST['name']
ob.pid = request.POST['pid']
ob.path = request.POST['path']
ob.save()
context = {'info':'添加成功!'}
except Exception as err:
print(err)
context = {'info':'添加失败!'}
return render(request,"myadmin/info.html",context)
# 执行商品类别信息删除
def delete(request,tid):
try:
# 获取被删除商品的子类别信息量,若有数据,就禁止删除当前类别
row = Types.objects.filter(pid=tid).count()
if row > 0:
context = {'info':'删除失败:此类别下还有子类别!'}
return render(request,"myadmin/info.html",context)
ob = Types.objects.get(id=tid)
ob.delete()
context = {'info':'删除成功!'}
except Exception as err:
print(err)
context = {'info':'删除失败!'}
return render(request,"myadmin/info.html",context)
# 打开商品类别信息编辑表单
def edit(request,tid):
try:
ob = Types.objects.get(id=tid)
context = {'type':ob}
return render(request,"myadmin/type/edit.html",context)
except Exception as err:
print(err)
context = {'info':'没有找到要修改的信息!'}
return render(request,"myadmin/info.html",context)
# 执行商品类别信息编辑
def update(request,tid):
try:
ob = Types.objects.get(id=tid)
ob.name = request.POST['name']
ob.save()
context = {'info':'修改成功!'}
except Exception as err:
print(err)
context = {'info':'修改失败!'}
return render(request,"myadmin/info.html",context)
...
<li class="nav-header">
商品类别管理
</li>
<li>
<a href="{% url 'myadmin_type_index' %}"><i class="icon-envelope"></i> 浏览商品类别</a>
</li>
<li>
<a href="{% url 'myadmin_type_add' 0 %}"><i class="icon-file"></i> 添加商品类别</a>
</li>
...
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h4>
商品类别信息管理
</h4>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>ID号</th>
<th>类别名称</th>
<th>父类别id</th>
<th>路径</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for vo in typeslist %}
<tr>
<td>{{ vo.id }}</td>
<td>{{ vo.pname}}|-- {{ vo.name }}</td>
<td>{{ vo.pid }}</td>
<td>{{ vo.path }}</td>
<td width="30%">
<a href="{% url 'myadmin_type_add' vo.id %}" class="view-link">添加子类别</a>
<a href="{% url 'myadmin_type_del' vo.id %}" class="view-link">删除</a>
<a href="{% url 'myadmin_type_edit' vo.id %}" class="view-link">编辑</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<ul>
<li class="disabled">
<a href="#">«</a>
</li>
<li class="active">
<a href="#">1</a>
</li>
<li>
<a href="#">2</a>
</li>
<li>
<a href="#">3</a>
</li>
<li>
<a href="#">4</a>
</li>
<li>
<a href="#">»</a>
</li>
</ul>
</div>
{% endblock %}
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h3>
商品类别信息管理
</h3>
<form id="edit-profile" action="{% url 'myadmin_type_insert' %}" class="form-horizontal" method="post">
<input type="hidden" name="pid" value="{{ pid }}"/>
<input type="hidden" name="path" value="{{ path }}"/>
{% csrf_token %}
<fieldset>
<legend>添加商品类别信息</legend>
<div class="control-group">
<label class="control-label" for="input01">父类别名称:</label>
<div class="controls">
<input type="text" name="pname" class="input-xlarge" id="input01" value="" placeholder="{{name}}"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">类别名称:</label>
<div class="controls">
<input type="text" name="name" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">添加</button> <button type="reset" class="btn">重置</button>
</div>
</fieldset>
</form>
{% endblock %}
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h3>
商品类别信息管理
</h3>
<form id="edit-profile" action="{% url 'myadmin_type_update' type.id %}" class="form-horizontal" method="post">
{% csrf_token %}
<fieldset>
<legend>编辑商品类别信息</legend>
<div class="control-group">
<label class="control-label" for="input01">类别名称:</label>
<div class="controls">
<input type="text" name="name" class="input-xlarge" id="input01" value="{{ type.name }}" />
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">保存</button> <button type="reset" class="btn">重置</button>
</div>
</fieldset>
</form>
{% endblock %}
[root@localhost myobject]# pwd
/python/myobject
[root@localhost myobject]# ls
manage.py myadmin myobject myweb static templates
[root@localhost myobject]# python3 manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
April 07, 2018 - 16:29:36
Django version 1.11, using settings 'myobject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
^C[root@localhost myobject]#
shopdb
中创建goods
表,若此表已存在请跳过CREATE TABLE `goods` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`typeid` int(11) unsigned NOT NULL,
`goods` varchar(32) NOT NULL,
`company` varchar(50) DEFAULT NULL,
`content` text,
`price` double(6,2) unsigned NOT NULL,
`picname` varchar(255) DEFAULT NULL,
`store` int(11) unsigned NOT NULL DEFAULT '0',
`num` int(11) unsigned NOT NULL DEFAULT '0',
`clicknum` int(11) unsigned NOT NULL DEFAULT '0',
`state` tinyint(1) unsigned NOT NULL DEFAULT '1',
`addtime` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `typeid` (`typeid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
myobject/common/models.py
模型文件,添加如下代码from django.db import models
from datetime import datetime
#商品信息模型
class Goods(models.Model):
typeid = models.IntegerField()
goods = models.CharField(max_length=32)
company = models.CharField(max_length=50)
content = models.TextField()
price = models.FloatField()
picname = models.CharField(max_length=255)
store = models.IntegerField(default=0)
num = models.IntegerField(default=0)
clicknum = models.IntegerField(default=0)
state = models.IntegerField(default=1)
addtime = models.DateTimeField(default=datetime.now)
def toDict(self):
return {'id':self.id,'typeid':self.typeid,'goods':self.goods,'company':self.company,'price':self.price,'picname':self.picname,'store':self.store,'num':self.num,'clicknum':self.clicknum,'state':self.state}
class Meta:
db_table = "goods" # 更改表名
from django.conf.urls import url
from myadmin.views import index,users,type,goods
urlpatterns = [
...
# 后台商品信息管理
url(r'^goods$', goods.index, name="myadmin_goods_index"),
url(r'^goods/add$', goods.add, name="myadmin_goods_add"),
url(r'^goods/insert$', goods.insert, name="myadmin_goods_insert"),
url(r'^goods/del/(?P<gid>[0-9]+)$', goods.delete, name="myadmin_goods_del"),
url(r'^goods/edit/(?P<gid>[0-9]+)$', goods.edit, name="myadmin_goods_edit"),
url(r'^goods/update/(?P<gid>[0-9]+)$', goods.update, name="myadmin_goods_update"),
]
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from common.models import Types,Goods
from PIL import Image
from datetime import datetime
import time,json,os
# ==============后台商品信息管理======================
# 浏览商品信息
def index(request):
# 执行数据查询,并放置到模板中
list = Goods.objects.all()
for ob in list:
ty = Types.objects.get(id=ob.typeid)
ob.typename = ty.name
context = {"goodslist":list}
return render(request,'myadmin/goods/index.html',context)
# 商品信息添加表单
def add(request):
# 获取商品的类别信息
list = Types.objects.extra(select = {'_has':'concat(path,id)'}).order_by('_has')
context = {"typelist":list}
return render(request,'myadmin/goods/add.html',context)
#执行商品类别信息添加
def insert(request):
try:
# 判断并执行图片上传,缩放等处理
myfile = request.FILES.get("pic", None)
if not myfile:
return HttpResponse("没有上传文件信息!")
# 以时间戳命名一个新图片名称
filename= str(time.time())+"."+myfile.name.split('.').pop()
destination = open(os.path.join("./static/goods/",filename),'wb+')
for chunk in myfile.chunks(): # 分块写入文件
destination.write(chunk)
destination.close()
# 执行图片缩放
im = Image.open("./static/goods/"+filename)
# 缩放到375*375:
im.thumbnail((375, 375))
# 把缩放后的图像用jpeg格式保存:
im.save("./static/goods/"+filename, 'jpeg')
# 缩放到220*220:
im.thumbnail((220, 220))
# 把缩放后的图像用jpeg格式保存:
im.save("./static/goods/m_"+filename, 'jpeg')
# 缩放到75*75:
im.thumbnail((75, 75))
# 把缩放后的图像用jpeg格式保存:
im.save("./static/goods/s_"+filename, 'jpeg')
# 获取商品信息并执行添加
ob = Goods()
ob.goods = request.POST['goods']
ob.typeid = request.POST['typeid']
ob.company = request.POST['company']
ob.price = request.POST['price']
ob.store = request.POST['store']
ob.content = request.POST['content']
ob.picname = filename
ob.state = 1
ob.addtime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
ob.save()
context = {'info':'添加成功!'}
except Exception as err:
print(err)
context = {'info':'添加失败!'}
return render(request,"myadmin/info.html",context)
# 执行商品信息删除
def delete(request,gid):
try:
# 获取被删除商品信的息量,先删除对应的图片
ob = Goods.objects.get(id=gid)
#执行图片删除
os.remove("./static/goods/"+ob.picname)
os.remove("./static/goods/m_"+ob.picname)
os.remove("./static/goods/s_"+ob.picname)
#执行商品信息的删除
ob.delete()
context = {'info':'删除成功!'}
except Exception as err:
print(err)
context = {'info':'删除失败!'}
return render(request,"myadmin/info.html",context)
# 打开商品类别信息编辑表单
def edit(request,gid):
try:
# 获取要编辑的信息
ob = Goods.objects.get(id=gid)
# 获取商品的类别信息
list = Types.objects.extra(select = {'_has':'concat(path,id)'}).order_by('_has')
# 放置信息加载模板
context = {"typelist":list,'goods':ob}
return render(request,"myadmin/goods/edit.html",context)
except Exception as err:
print(err)
context = {'info':'没有找到要修改的信息!'}
return render(request,"myadmin/info.html",context)
# 执行商品类别信息编辑
def update(request,gid):
try:
b = False
oldpicname = request.POST['oldpicname']
if None != request.FILES.get("pic"):
myfile = request.FILES.get("pic", None)
if not myfile:
return HttpResponse("没有上传文件信息!")
# 以时间戳命名一个新图片名称
filename = str(time.time())+"."+myfile.name.split('.').pop()
destination = open(os.path.join("./static/goods/",filename),'wb+')
for chunk in myfile.chunks(): # 分块写入文件
destination.write(chunk)
destination.close()
# 执行图片缩放
im = Image.open("./static/goods/"+filename)
# 缩放到375*375:
im.thumbnail((375, 375))
# 把缩放后的图像用jpeg格式保存:
im.save("./static/goods/"+filename, 'jpeg')
# 缩放到220*220:
im.thumbnail((220, 220))
# 把缩放后的图像用jpeg格式保存:
im.save("./static/goods/m_"+filename, 'jpeg')
# 缩放到75*75:
im.thumbnail((75, 75))
# 把缩放后的图像用jpeg格式保存:
im.save("./static/goods/s_"+filename, 'jpeg')
b = True
picname = filename
else:
picname = oldpicname
ob = Goods.objects.get(id=gid)
ob.goods = request.POST['goods']
ob.typeid = request.POST['typeid']
ob.company = request.POST['company']
ob.price = request.POST['price']
ob.store = request.POST['store']
ob.content = request.POST['content']
ob.picname = picname
ob.state = request.POST['state']
ob.save()
context = {'info':'修改成功!'}
if b:
os.remove("./static/goods/m_"+oldpicname) #执行老图片删除
os.remove("./static/goods/s_"+oldpicname) #执行老图片删除
os.remove("./static/goods/"+oldpicname) #执行老图片删除
except Exception as err:
print(err)
context = {'info':'修改失败!'}
if b:
os.remove("./static/goods/m_"+picname) #执行新图片删除
os.remove("./static/goods/s_"+picname) #执行新图片删除
os.remove("./static/goods/"+picname) #执行新图片删除
return render(request,"myadmin/info.html",context)
...
<li class="nav-header">
商品信息管理
</li>
<li>
<a href="{% url 'myadmin_goods_index' %}"><i class="icon-list-alt"></i> 浏览商品信息</a>
</li>
<li>
<a href="{% url 'myadmin_goods_add' %}"><i class="icon-list-alt"></i> 添加商品信息</a>
</li>
...
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h4>
商品信息管理
</h4>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>id号</th>
<th>商品名称</th>
<th>商品类别</th>
<th>图片</th>
<th>单价</th>
<th>点击量</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for vo in goodslist %}
<tr>
<td>{{ vo.id }}</td>
<td>{{ vo.goods }}</td>
<td>{{ vo.typename }}</td>
<td><img src="/static/goods/s_{{ vo.picname }}" width="60"/></td>
<td>{{ vo.price }}</td>
<td>{{ vo.clicknum }}</td>
<td>
{% if vo.state == 1 %}
新添加
{% elif vo.state == 2 %}
在售
{% else %}
下架
{% endif %}
</td>
<td>
<a href="{% url 'myadmin_goods_del' vo.id %}" class="view-link">删除</a>
<a href="{% url 'myadmin_goods_edit' vo.id %}" class="view-link">编辑</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<ul>
<li class="disabled">
<a href="#">«</a>
</li>
<li class="active">
<a href="#">1</a>
</li>
<li>
<a href="#">2</a>
</li>
<li>
<a href="#">3</a>
</li>
<li>
<a href="#">4</a>
</li>
<li>
<a href="#">»</a>
</li>
</ul>
</div>
{% endblock %}
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h3>
商品信息管理
</h3>
<form id="edit-profile" action="{% url 'myadmin_goods_insert' %}" class="form-horizontal" method="post" enctype="multipart/form-data">
{% csrf_token %}
<fieldset>
<legend>添加商品信息</legend>
<div class="control-group">
<label class="control-label" for="input01">商品类别:</label>
<div class="controls">
<select name="typeid">
{% for vo in typelist %}
<option
{% if vo.pid == 0 %}
disabled
{% endif %}
value="{{ vo.id }}">{{ vo.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">商品名称:</label>
<div class="controls">
<input type="text" name="goods" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">生产厂家:</label>
<div class="controls">
<input type="text" name="company" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">单价:</label>
<div class="controls">
<input type="text" name="price" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">库存量:</label>
<div class="controls">
<input type="text" name="store" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">商品图片:</label>
<div class="controls">
<input type="file" name="pic" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">商品简介:</label>
<div class="controls">
<textarea cols="40" style="width:450px" rows="10" name="content"></textarea>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">添加</button> <button type="reset" class="btn">重置</button>
</div>
</fieldset>
</form>
{% endblock %}
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h3>
商品信息管理
</h3>
<form id="edit-profile" action="{% url 'myadmin_goods_update' goods.id %}" class="form-horizontal" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="oldpicname" value="{{ goods.picname }}"/>
<fieldset>
<legend>编辑商品信息</legend>
<div class="control-group">
<label class="control-label" for="input01">商品类别:</label>
<div class="controls">
<select name="typeid">
{% for vo in typelist %}
<option
{% if vo.pid == 0 %}
disabled
{% endif %}
{% if vo.id == goods.typeid %}
selected
{% endif %}
value="{{ vo.id }}">{{ vo.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">商品名称:</label>
<div class="controls">
<input type="text" name="goods" value="{{ goods.goods }}" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">生产厂家:</label>
<div class="controls">
<input type="text" name="company" value="{{ goods.company }}" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">单价:</label>
<div class="controls">
<input type="text" name="price" value="{{ goods.price }}" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">库存量:</label>
<div class="controls">
<input type="text" name="store" value="{{ goods.store }}" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">商品图片:</label>
<div class="controls">
<input type="file" name="pic" class="input-xlarge" id="input01"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">状态:</label>
<div class="controls">
<input type="radio" name="state" class="input-xlarge" id="input01"
{% if goods.state == 1 %}
checked
{% endif %}
value="1" /> 新商品
<input type="radio" name="state" class="input-xlarge" id="input01"
{% if goods.state == 2 %}
checked
{% endif %}
value="2" /> 在售
<input type="radio" name="state" class="input-xlarge" id="input01"
{% if goods.state == 3 %}
checked
{% endif %}
value="3" /> 已下架
</div>
</div>
<div class="control-group">
<label class="control-label" for="input01">商品简介:</label>
<div class="controls">
<textarea cols="40" style="width:450px" rows="10" name="content">{{ goods.content }}</textarea>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">保存</button> <button type="reset" class="btn">重置</button>
</div>
</fieldset>
</form>
<br/>
<img src="/static/goods/m_{{ goods.picname }}"/>
{% endblock %}
[root@localhost myobject]# pwd
/python/myobject
[root@localhost myobject]# ls
manage.py myadmin myobject myweb static templates
[root@localhost myobject]# python3 manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
April 08, 2018 - 12:20:30
Django version 1.11, using settings 'myobject.settings'
Starting development server at http://0:8000/
Quit the server with CONTROL-C.
^C[root@localhost myobject]#
url(r'^goods/(?P<pIndex>[0-9]+)$', ... ... ),
,具体如下:from django.conf.urls import url
from myadmin.views import index,users,type,goods
urlpatterns = [
...
# 后台商品信息管理
url(r'^goods/(?P<pIndex>[0-9]+)$', goods.index, name="myadmin_goods_index"),
url(r'^goods/add$', goods.add, name="myadmin_goods_add"),
url(r'^goods/insert$', goods.insert, name="myadmin_goods_insert"),
url(r'^goods/del/(?P<gid>[0-9]+)$', goods.delete, name="myadmin_goods_del"),
url(r'^goods/edit/(?P<gid>[0-9]+)$', goods.edit, name="myadmin_goods_edit"),
url(r'^goods/update/(?P<gid>[0-9]+)$', goods.update, name="myadmin_goods_update"),
]
Q
和分页Paginator
:from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.core.paginator import Paginator
from common.models import Types,Goods
from PIL import Image
from datetime import datetime
import time,json,os
# ==============后台商品信息管理======================
# 浏览商品信息
def index(request,pIndex):
'''浏览信息'''
#获取商品类别信息
tlist = Types.objects.extra(select={'_has':'concat(path,id)'}).order_by('_has')
for ob in tlist:
ob.pname = '. . .'*(ob.path.count(',')-1)
#获取商品信息查询对象
mod = Goods.objects
mywhere=[] #定义一个用于存放搜索条件列表
# 获取、判断并封装关keyword键搜索
kw = request.GET.get("keyword",None)
if kw:
# 查询商品名中只要含有关键字的都可以
list = mod.filter(goods__contains=kw)
mywhere.append("keyword="+kw)
else:
list = mod.filter()
# 获取、判断并封装商品类别typeid搜索条件
typeid = request.GET.get('typeid','0')
if typeid != '0':
tids = Types.objects.filter(Q(id=typeid) | Q(pid=typeid)).values_list('id',flat=True)
list = list.filter(typeid__in=tids)
mywhere.append("typeid="+typeid)
# 获取、判断并封装商品状态state搜索条件
state = request.GET.get('state','')
if state != '':
list = list.filter(state=state)
mywhere.append("state="+state)
#执行分页处理
pIndex = int(pIndex)
page = Paginator(list,5) #以5条每页创建分页对象
maxpages = page.num_pages #最大页数
#判断页数是否越界
if pIndex > maxpages:
pIndex = maxpages
if pIndex < 1:
pIndex = 1
list2 = page.page(pIndex) #当前页数据
plist = page.page_range #页码数列表
#遍历商品信息,并获取对应的商品类别名称,以typename名封装
for vo in list2:
ty = Types.objects.get(id=vo.typeid)
vo.typename = ty.name
#封装信息加载模板输出
context = {'typelist':tlist,"goodslist":list2,'plist':plist,'pIndex':pIndex,'maxpages':maxpages,'mywhere':mywhere,'typeid':int(typeid)}
return render(request,"myadmin/goods/index.html",context)
# 商品信息添加表单
....
....
myadmin_goods_index
添加一个默认页号参数1: ...
<li class="nav-header">
商品信息管理
</li>
<li>
<a href="{% url 'myadmin_goods_index' 1 %}"><i class="icon-list-alt"></i> 浏览商品信息</a>
</li>
<li>
<a href="{% url 'myadmin_goods_add' %}"><i class="icon-list-alt"></i> 添加商品信息</a>
</li>
...
搜索表单
和页码信息
, 注意: { { mywhere|join:'&' } }
是为了下一页维持搜索条件用的:{% extends "myadmin/base.html" %}
{% block mainbody %}
<h2>
商品信息浏览
</h2>
<form class="form-inline" action="{% url 'myadmin_goods_index' 1 %}" method="get">
<label>关键字:</label>
<input type="text" name="keyword" value="{{request.GET.keyword}}" class="input-small" placeholder="商品名称">
<label> 类别:</label>
<select name="typeid" class="span2">
<option value="0">全部</option>
{% for vo in typelist %}
<option value="{{ vo.id }}" {% if typeid == vo.id %}selected{% endif %}>{{vo.pname}}|--{{ vo.name }}</option>
{% endfor %}
</select>
<label> 状态:</label>
<select name="state" class="span1">
<option value="">全部</option>
<option value="1" {% if request.GET.state == '1' %}selected{% endif %}>新商品</option>
<option value="2" {% if request.GET.state == '2' %}selected{% endif %}>在售</option>
<option value="3" {% if request.GET.state == '3' %}selected{% endif %}>已下架</option>
</select>
<button type="submit" class="btn">搜索</button>
<a href="{% url 'myadmin_goods_index' 1 %}" class="btn">全部</a>
</form>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>id号</th>
<th>商品名称</th>
<th>商品类别</th>
<th>图片</th>
<th>价格</th>
<th>点击量</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for vo in goodslist %}
<tr>
<td>{{ vo.id }}</td>
<td>{{ vo.goods }}</td>
<td>{{ vo.typename }}</td>
<td><img src="/static/goods/s_{{ vo.picname }}" width="40"/></td>
<td>{{ vo.price }}</td>
<td>{{ vo.clicknum }}</td>
<td>
{% if vo.state == 1 %}
<span style="color:green">新商品</span>
{% elif vo.state == 2 %}
在售
{% elif vo.state == 3 %}
已下架
{% else %}
<span style="color:red">无效状态</span>
{% endif %}
</td>
<td>
<a href="{% url 'myadmin_goods_edit' vo.id %}" class="btn btn-mini btn-primary">编辑</a>
<a href="{% url 'myadmin_goods_del' vo.id %}" class="btn btn-mini btn-danger">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<ul>
<li>
<a href="{% url 'myadmin_goods_index' pIndex|add:-1 %}?{{ mywhere|join:'&' }}">«</a>
</li>
{% for p in plist %}
<li {% if pIndex == p %}class="active"{% endif %}>
<a href="{% url 'myadmin_goods_index' p %}?{{ mywhere|join:'&' }}">{{p}}</a>
</li>
{% endfor %}
<li>
<a href="{% url 'myadmin_goods_index' pIndex|add:1 %}?{{ mywhere|join:'&' }}">»</a>
</li>
</ul>
</div>
{% endblock %}
/myobject/
├── manage.py
├── myobject/ 项目总目录
│ ├── ... 略
│
├── common/ 公共应用目录
│ ├── ... 略
│
├── myadmin/ 网站后台应用目录
│ ├── ... 略
│
├── web 网站前台应用
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ ├── views
│ │ ├── index.py web前台主视图
│ │ ├── vip.py 会员操作视图
│ │ ├── cart.py 购物车管理视图
│ │ └── orders.py 订单处理视图
│ ├── models.py
│ ├── tests.py
│ └── urls.py 网站前台的URL路由配置
│
├── ueditor 百度编辑器(富文本编辑器)目录
│ ├── ... 略
│
├── templates 模板目录
│ ├── myadmin 后台模板总目录
│ │ ├── ... 略
│ │
│ ├── web 前台模板目录
│ │ ├── base.html
│ │ ├── index.html
│ │ ├── list.html
│ │ ├── detail.html
│ │ ├── login.html
│ │ ├── reg.html
│ │ └── ......
│
├── static 静态资源目录
│ ├── myadmin 后台静态资源
│ │ ├──....
│ │
│ ├── web 网站前台静态资源
│ │ ├──....
│ │ ├──....
from django.conf.urls import url
from web.views import index,cart,orders,vip
urlpatterns = [
# 前台首页
url(r'^$', index.index, name="index"), #商城首页
url(r'^list$', index.lists, name="list"),# 商品列表
url(r'^list/(?P<pIndex>[0-9]+)$', index.lists, name="list"),# 商品列表
url(r'^detail/(?P<gid>[0-9]+)$', index.detail, name="detail"),#商品详情
# 会员登录和退出路由配置
url(r'^login$', index.login, name="login"),
url(r'^dologin$', index.dologin, name="dologin"),
url(r'^logout$', index.logout, name="logout"),
# 购物车信息管理路由配置
url(r'^cart$', cart.index, name="cart_index"),
url(r'^cart/add/(?P<gid>[0-9]+)$', cart.add, name="cart_add"),
url(r'^cart/del/(?P<gid>[0-9]+)$', cart.delete, name="cart_del"),
url(r'^cart/clear$', cart.clear, name="cart_clear"),
url(r'^cart/change$', cart.change, name="cart_change"),
# 订单处理
url(r'^orders/add$', orders.add,name='orders_add'), #订单的表单页
url(r'^orders/confirm$', orders.confirm,name='orders_confirm'), #订单确认页
url(r'^orders/insert$', orders.insert,name='orders_insert'), #执行订单添加操作
# 会员中心
url(r'^vip/orders$', vip.viporders,name='vip_orders'), #会员中心我的订单
url(r'^vip/odstate$', vip.odstate,name='vip_odstate'), #修改订单状态(确认收货)
#url(r'^vip/info$', vip.info,name='vip_info'), #会员中心的个人信息
#url(r'^vip/update$', vip.update,name='vip_update'), #执行修改会员信息
#url(r'^vip/resetps$', vip.resetps,name='vip_resetps'), #重置密码表单
#url(r'^vip/doresetps$', vip.doresetps,name='vip_doresetps'), #执行重置密码
]
css
、fonts
、img
、js
复制到项目的static/web/目录下。from django.conf.urls import url
from web.views import index
urlpatterns = [
# 前台首页
url(r'^$', index.index, name="index"), #商城首页
url(r'^list$', index.lists, name="list"),# 商品列表
url(r'^detail/(?P<gid>[0-9]+)$', index.detail, name="detail"),#商品详情
]
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index(request):
'''项目前台首页'''
return render(request,"web/index.html")
def lists(request,pIndex=1):
'''商品列表页'''
return render(request,"web/list.html")
def detail(request,gid):
'''商品详情页'''
return render(request,"web/detail.html")
base.html
、index.html
、list.html
、detail.html
具体参考老师的授课。"\./public/(.*?)"` 换成 `"{% static 'web/\1' %}"
shopdb
中已存在数据表users
,并且内有测试数据。myobject/common/models.py
模型文件中,已存在Users
模型类的定义。from django.conf.urls import url
from web.views import index
urlpatterns = [
#网站前台
url(r'^$',index.index,name="index"), #首页
url(r'^list$',index.lists,name="list"), #商品列表展示
#url(r'^list/(?P<pIndex>[0-9]+)$',index.lists,name="list"), #分页商品列表展示
url(r'^detail/(?P<gid>[0-9]+)$',index.detail,name="detail"), #商品详情
# 会员及个人中心等路由配置
url(r'^login$', index.login, name="login"),
url(r'^dologin$', index.dologin, name="dologin"),
url(r'^logout$', index.logout, name="logout"),
]
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from common.models import Users
# =============商品展示========================
def index(request):
'''项目前台首页'''
return render(request,"web/index.html")
def lists(request,pIndex=1):
'''商品列表页'''
return render(request,"web/list.html")
def detail(request,gid):
'''商品详情页'''
return render(request,"web/detail.html")
# ==============前台会员登录====================
def login(request):
'''会员登录表单'''
return render(request,'web/login.html')
def dologin(request):
'''会员执行登录'''
# 校验验证码
verifycode = request.session['verifycode']
code = request.POST['code']
if verifycode != code:
context = {'info':'验证码错误!'}
return render(request,"web/login.html",context)
try:
#根据账号获取登录者信息
user = Users.objects.get(username=request.POST['username'])
#判断当前用户是否是后台管理员用户
if user.state == 0 or user.state == 1:
# 验证密码
import hashlib
m = hashlib.md5()
m.update(bytes(request.POST['password'],encoding="utf8"))
if user.password == m.hexdigest():
# 此处登录成功,将当前登录信息放入到session中,并跳转页面
request.session['vipuser'] = user.toDict()
return redirect(reverse('index'))
else:
context = {'info':'登录密码错误!'}
else:
context = {'info':'此用户为非法用户!'}
except:
context = {'info':'登录账号错误!'}
return render(request,"web/login.html",context)
def logout(request):
'''会员退出'''
# 清除登录的session信息
del request.session['vipuser']
# 跳转登录页面(url地址改变)
return redirect(reverse('login'))
...
<li class="layout-header-service-item" id="layoutHeaderUser">
<a class="layout-header-service-link g-user" style="background: #fff;width:auto;" href="#">
<i class="glyphicon glyphicon-user"></i>
<span>{{request.session.vipuser.name}}</span>
</a>
<div class="layout-user-downmenu">
<ul class="layout-user-downmenu-list">
{% if request.session.vipuser %}
<li class="layout-user-downmenu-item">
<a href="#" class="layout-user-downmenu-link" data-mtype="wmz_public_grzx_myorder">个人中心</a>
</li>
<li class="layout-user-downmenu-item">
<a href="#" class="layout-user-downmenu-link" data-mtype="wmz_public_grzx_myorder">我的订单</a>
</li>
<li class="layout-user-downmenu-item">
<a href="{% url 'logout' %}" class="layout-user-downmenu-link" data-mtype="wmz_public_grzx_mformy">退出</a>
</li>
{% else %}
<li class="layout-user-downmenu-item">
<a href="{% url 'login'%}" class="layout-user-downmenu-link">立即登录</a>
</li>
<li class="layout-user-downmenu-item">
<a href="#" target="_blank" class="layout-user-downmenu-link" data-mtype="wmz_public_grzx_register">立即注册</a>
</li>
{% endif %}
</ul>
</div>
</li>
...
{% load static from staticfiles %}
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title> Flyme 账号 - 登录</title>
<meta name="description" content="欢迎登录和注册 Flyme 账号,您可以体验手机云服务功能,包括:在线下载应用,同步手机数据和查找手机等,让您的手机管理更加智能。" />
<meta name="keywords" content="魅族 meizu 登录flyme 云服务 查找手机 充值账号 MX M9 MX2" /> <link href="{% static 'web/img/favicon.ico' %}" rel="shortcut icon" type="image/x-icon"/>
<link href="{% static 'web/img/favicon.ico' %}" rel="icon" type="image/x-icon">
<!-- Bootstrap -->
<link href="{% static 'web/css/bootstrap.min.css' %}" rel="stylesheet">
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="{% static 'web/js/jquery-1.12.4.min.js' %}"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="{% static 'web/js/bootstrap.min.js' %}"></script>
<!-- 兼任ie9以下 -->
<!--[if lt IE 9]>
<script src="http://cdn.bootcss.com/html5shiv/3.7.0/html5shiv.min.js"></script>
<script src="http://cdn.bootcss.com/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<!-- 自定义 -->
<link rel="stylesheet" type="text/css" href="{% static 'web/css/global.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'web/css/register.css' %}">
<script type="text/javascript" src="{% static 'web/js/rem.js' %}"></script>
<script type="text/javascript" src="{% static 'web/js/topNav.js' %}"></script>
</head>
<body>
<!-- 导航 -->
<div class="layout-header hidden-xs hidden-sm" id="scroll-wrap">
<nav class="navbar navbar-default header ">
<div class="container clearfix">
<div class="layout-header-logo navbar-left">
<a href="{% url 'index' %}" class="layout-header-logo-link" alt="魅族科技">
<img src="{% static 'web/img/logo.png' %}">
</a>
</div>
</div>
</nav>
</div><!-- 导航 E-->
<!-- 主内容区域 -->
<div id="content" class="content">
<div class="container-fluid">
<div class="banner-box hidden-xs hidden-sm">
<div class="container">
<form id="mainForm" name="mainForm" action="{% url 'dologin' %}" method="post" class="main-form">
{% csrf_token %}
<div class="tab-title">
<a class="linkAGray" id="toAccountLogin" href="javascript:void(0);">账号登录</a>
</div><br/>
{% if info %}
<div class="tip-box">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<i class="glyphicon glyphicon-exclamation-sign"></i>
<span class="tip-font">{{info}}</span>
<span aria-hidden="true" class="cha">×</span>
</button>
</div>
{% endif %}
<div class="normalInput cycode-box fieldInput" id="cycode-box">
<div class="cycode-selectbox">
<input class="ipt-account inp-focus" name="username" id="account" maxlength="50" placeholder="登录账号" autocomplete="off">
</div>
</div>
<div class="normalInput fieldInput passwd-box">
<input class="inp-focus" name="password" id="password" maxlength="16" autocomplete="off" placeholder="登录密码" type="password"/>
</div>
<div class="normalInput fieldInput passwd-box">
<input class="inp-focus" name="code" style="width:100px;" maxlength="16" placeholder="验证码" autocomplete="off" type="text" />
<img src="{% url 'myadmin_verify' %}?id=1" onclick="this.src='{% url 'myadmin_verify' %}?sn='+Math.random()"/>
</div>
<a id="register" href="javascript:document.mainForm.submit();" class="fullBtnBlue">登录</a>
<div class="transferField">
<a class="go2forgetpwd linkABlue rememberFieldForA" href="#">忘记密码?</a>
<a class="go2register linkABlue" href="./register.html" id="toRegister">注册</a>
<span>测试号:zhangsan 密码:123</span>
</div>
</form>
</div>
</div>
<!-- 移动端结构 -->
<form id="mainForm" class="main-form app-main-form">
<div class="tab-title">
<a class="linkAGray" id="toAccountLogin" href="javascript:void(0);">账号登录</a>
</div>
<div class="tip-box visiblility-hidden">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<i class="glyphicon glyphicon-exclamation-sign"></i>
<span class="tip-font"></span>
<span aria-hidden="true" class="cha">×</span>
</button>
</div>
<div class="normalInput cycode-box show-cycode" id="cycode-box">
<div class="cycode-selectbox">
<input id="phone" name="phone" class="ipt-phone inp-focus" maxlength="11" placeholder="手机号码" autocomplete="off">
</div>
</div>
<div class="normalInput box-input">
<input class="pswInput inp-focus" name="kapkey" id="kapkey" maxlength="6" placeholder="密码" autocomplete="off" tabindex="3" type="text">
</div>
<a id="register" class="fullBtnBlue">登录</a>
<div class="transferField">
<a class="go2forgetpwd linkABlue rememberFieldForA" href="#">忘记密码?</a>
<a class="go2register linkABlue" href="./register.html" id="toRegister">注册</a>
</div>
</form>
<!-- 移动端结构 E-->
</div>
</div>
<!-- 主内容区域 E-->
<!-- 底部区域 -->
<div id="flymeFooter " class="footerWrap hidden-xs hidden-sm">
<div class="container">
<div class="footer-layer1">
<div class="footer-innerLink">
<a href="#" target="_blank" title="关于魅族">关于魅族</a>
<img class="foot-line" src="{% static 'web/img/space.gif' %}">
<a href="#" target="_blank" title="工作机会">工作机会</a>
<img class="foot-line" src="{% static 'web/img/space.gif' %}">
<a href="#" target="_blank" title="联系我们">联系我们</a>
<img class="foot-line" src="{% static 'web/img/space.gif' %}">
<a href="#" target="_blank" title="法律声明">法律声明</a>
<img class="foot-line" src="{% static 'web/img/space.gif' %}">
<div href="javascript:void(0);" id="globalName" class="footer-language" title="简体中文">
简体中文
<div id="globalContainer" class="footer-language_menu">
<a href="#" id="i18n-link" title="English" class="ClobalItem">English</a>
</div>
</div>
</div>
<div class="footer-service">
<span class="service-label">客服热线</span>
<span class="service-num">400-888-6666</span>
<a id="service-online" class="service-online" href="javascript:void(0);" title="在线客服">在线客服</a>
</div>
<div class="footer-outerLink">
<a class="footer-sinaMblog" href="#" target="_blank"><i class="i_icon"></i></a>
<a id="footer-weChat" class="footer-weChat" href="javascript:void(0);" target="_blank"><i class="i_icon"></i></a>
<a class="footer-qzone" href="#" target="_blank"><i class="i_icon"></i></a>
</div>
</div>
<div class="clear"></div>
<div id="flymeCopyright" class="copyrightWrap">
<div class="copyrightInner">
<span>©2018 Meizu Telecom Equipment Co., Ltd. All rights reserved.</span>
<a href="#" class="linkAGray" target="_blank">备案号: 京ICP备123456789号-4</a>
<a href="#" class="linkAGray" target="_blank">经营许可证编号: 京A1-20280198</a>
<a target="_blank" href="#" class="linkAGray">营业执照</a>
</div>
</div>
</div>
</div>
<!-- 底部区域 E -->
<script type="text/javascript">
//
nLogin();
</script>
</body>
</html>
/list
或/list/页号
请求中分类分页展示商品信息/detail/gid号
请求中展示指定商品id号的商品信息shopdb
中已存在数据表goods
和type
,并且内有测试数据。myobject/common/models.py
模型文件中,已存在Goods
和Types
模型类的定义。from django.conf.urls import url
from web.views import index
urlpatterns = [
#网站前台
url(r'^$',index.index,name="index"), #首页
url(r'^list$',index.lists,name="list"), #商品列表展示
#url(r'^list/(?P<pIndex>[0-9]+)$',index.lists,name="list"), #分页商品列表展示
url(r'^detail/(?P<gid>[0-9]+)$',index.detail,name="detail"), #商品详情
# 会员及个人中心等路由配置
url(r'^login$', index.login, name="login"),
url(r'^dologin$', index.dologin, name="dologin"),
url(r'^logout$', index.logout, name="logout"),
]
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator
from common.models import Users,Types,Goods
# 公共信息加载
def loadinfo(request):
'''公共信息加载'''
context = {}
lists = Types.objects.filter(pid=0)
context['typelist'] = lists
return context
# =============商品展示========================
def index(request):
'''项目前台首页'''
context = loadinfo(request)
return render(request,"web/index.html",context)
def lists(request,pIndex=1):
'''商品列表页(搜索&分页)'''
context = loadinfo(request)
#获取商品信息查询对象
mod = Goods.objects
mywhere=[] #定义一个用于存放搜索条件列表
#判断添加搜索条件
tid = int(request.GET.get('tid',0))
if tid > 0:
list = mod.filter(typeid__in=Types.objects.only('id').filter(pid=tid))
mywhere.append("tid="+str(tid))
else:
list = mod.filter()
#获取、判断并封装关keyword键搜索
kw = request.GET.get("keyword",None)
if kw:
# 查询商品名中只要含有关键字的都可以
list = list.filter(goods__contains=kw)
mywhere.append("keyword="+kw)
#执行分页处理
pIndex = int(pIndex)
page = Paginator(list,5) #以5条每页创建分页对象
maxpages = page.num_pages #最大页数
#判断页数是否越界
if pIndex > maxpages:
pIndex = maxpages
if pIndex < 1:
pIndex = 1
list2 = page.page(pIndex) #当前页数据
plist = page.page_range #页码数列表
#封装信息加载模板输出
context['goodslist'] = list2
context['plist'] = plist
context['pIndex'] = pIndex
context['maxpages'] = maxpages
context['mywhere'] = mywhere
context['tid'] = int(tid)
return render(request,"web/list.html",context)
def detail(request,gid):
'''商品详情页'''
context = loadinfo(request)
#加载商品详情信息
ob = Goods.objects.get(id=gid)
ob.clicknum += 1 # 点击量加1
ob.save()
context['goods'] = ob
return render(request,"web/detail.html",context)
# ==============前台会员登录====================
# 略(上节中已编写)... ...
...
<ul class="nav navbar-nav navbar-right layout-header-nav clearfix">
<li class="layout-header-nav-item">
<a href="{% url 'index' %}" class="layout-header-nav-link">网站首页</a><p class="line-top hidden-xs"></p>
</li>
<li class="layout-header-nav-item"><a href="{% url 'list' %}" class="layout-header-nav-link">全部商品</a></li>
{% for type in typelist %}
<li class="layout-header-nav-item">
<a href="{% url 'list' %}?tid={{ type.id }}" class="layout-header-nav-link">{{ type.name }}</a>
</li>
{% endfor %}
<li class="layout-header-nav-item"><a href="#" class="layout-header-nav-link">社区</a></li>
</ul>
...
...
<!-- 商品列表 -->
<div class="goods-list">
<div class="row">
{% for goods in goodslist %}
<div class="col-md-3 col-sm-6 col-xs-6">
<div class="gl-item">
<div class="compare-btn-list" >
<i class="iconfont icon-duibi compare-duibi"></i>
<span class="hidden-xs hidden-sm">对比</span>
</div>
<div class="gl-item-wrap">
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active mod-pic" id="list-p1">
<a href="{% url 'detail' goods.id %}">
<img class="lazy j-modProduct" src="/static/goods/m_{{ goods.picname }}" width="220" height="220">
</a>
</div>
</div>
<!-- Nav tabs -->
<div class="item-slide j-pro-wrap hidden-xs hidden-sm">
<ul class="nav nav-tabs " role="tablist">
<li role="presentation" class="active">
<a href="#list-p1" aria-controls="list-p1" role="tab" data-toggle="tab">
<img class="lazy" src="/static/goods/s_{{ goods.picname }}" style="display: inline;" width="40" height="40">
</a>
</li>
</ul>
</div>
<div class="slide-btn j-modBtns" style="display: none;">
<span class="prev iconfont disabled"></span>
<span class="next iconfont"></span>
</div>
<h2>{{ goods.goods}}</h2>
<h3 class="red" title="双11促销:满500,减100!">
双11促销:满500,减100!
</h3>
<dd class="mod-price">
<span>¥</span>
<span class="vm-price">{{ goods.price }}</span>
<span class="vm-start">起</span>
</dd>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<!-- 商品列表 -->
<nav aria-label="Page navigation" class="text-center">
<ul class="pagination">
<li>
<a href="{% url 'list' pIndex|add:-1 %}?{{ mywhere|join:'&' }}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% for p in plist %}
<li {% if pIndex == p %}class="active"{% endif %}>
<a href="{% url 'list' p %}?{{ mywhere|join:'&' }}">{{p}}</a>
</li>
{% endfor %}
<li>
<a href="{% url 'list' pIndex|add:1 %}?{{ mywhere|join:'&' }}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
...
在详情模板中输出部分商品信息即可
shopdb
中已存在数据表goods
,并且内有测试数据。django_session
表。myobject/common/models.py
模型文件中,已存在Goods
模型类的定义。Goods
模型类中已经定义了toDict(self)
方法: # 注意:返回此商品的字典格式
def toDict(self):
return {'id':self.id,'typeid':self.typeid,'goods':self.goods,'company':self.company,'price':self.price,'picname':self.picname,'store':self.store,'num':self.num,'clicknum':self.clicknum,'state':self.state}
立即购买
按钮,完成向添加购物车操作的传值和跳转: <form action="{% url 'cart_add' goods.id %}" method="post">
{% csrf_token %}
<div class="property-buy">
<p class="vm-message" id="J_message"></p>
<dl class="property-buy-quantity">
<dt class="vm-metatit">数<span class="s-space"></span><span class="s-space"></span>量:</dt>
<dd class="clearfix">
<div class="mod-control">
<a title="减少" href="javascript:;" class="vm-minus disabled">-</a>
<input value="1" name="m" id="J_quantity" data-max="5" type="text">
<a title="增加" href="javascript:;" class="vm-plus">+</a>
</div>
</dd>
</dl>
<div class="property-buy-action">
<button data-mtype="store_de_buy" type="submit" id="J_btnBuy" class="btn btn-danger btn-lg mr20">立即购买</button>
<a data-mtype="store_de_cart" href="javascript:void(0);" id="J_btnAddCart" class="btn btn-primary btn-lg hide" style="display:inline-block;"><i></i>加入购物车</a>
<span class="vm-service" id="J_panicBuyingWrap"></span>
</div>
</div>
</form>
from django.conf.urls import url
from web.views import index,cart
urlpatterns = [
#网站前台
# ... ...
# 会员及个人中心等路由配置
# ... ...
# 购物车路由
url(r'^cart$', cart.index,name='cart_index'), #浏览购物车
url(r'^cart/add/(?P<gid>[0-9]+)$', cart.add,name='cart_add'), #添加购物车
url(r'^cart/del/(?P<gid>[0-9]+)$', cart.delete,name='cart_del'), #从购物车中删除一个商品
url(r'^cart/clear$', cart.clear,name='cart_clear'), #清空购物车
url(r'^cart/change$', cart.change,name='cart_change'), #更改购物车中商品数量
]
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from common.models import Goods,Types
# 公共信息加载
def loadinfo(request):
'''公共信息加载'''
context = {}
lists = Types.objects.filter(pid=0)
context['typelist'] = lists
return context
def index(request):
'''浏览购物车'''
context = loadinfo(request)
if 'shoplist' not in request.session:
request.session['shoplist']={}
return render(request,"web/cart.html",context)
def add(request,gid):
'''在购物车中放入商品信息'''
#获取要放入购物车中的商品信息
goods = Goods.objects.get(id=gid)
shop = goods.toDict();
shop['m'] = int(request.POST.get('m',1)) #添加一个购买量属性m
#从session获取购物车信息,没有默认空字典
shoplist = request.session.get('shoplist',{})
#判断此商品是否在购物车中
if gid in shoplist:
#商品数量加
shoplist[gid]['m']+=shop['m']
else:
#新商品添加
shoplist[gid]=shop
#将购物车信息放回到session
request.session['shoplist'] = shoplist
#重定向到浏览购物车页
return redirect(reverse('cart_index'))
#return render(request,"web/cart.html")
def delete(request,gid):
'''删除一个商品'''
shoplist = request.session['shoplist']
del shoplist[gid]
request.session['shoplist'] = shoplist
return redirect(reverse('cart_index'))
def clear(request):
'''清空购物车'''
context = loadinfo(request)
request.session['shoplist'] = {}
return render(request,"web/cart.html",context)
def change(request):
'''更改购物车中的商品信息'''
#context = loadinfo(request)
shoplist = request.session['shoplist']
#获取信息
shopid = request.GET.get('gid','0')
num = int(request.GET['num'])
if num<1:
num = 1
shoplist[shopid]['m'] = num #更改商品数量
request.session['shoplist'] = shoplist
return redirect(reverse('cart_index'))
#return render(request,"web/cart.html",context)
...
<li class="layout-header-service-item layout-header-service-cart" id="layoutHeaderCart">
<a class="layout-header-service-link" href="{% url 'cart_index' %}" data-mtype="wmz_public_yt_cart">
<i class="glyphicon glyphicon-shopping-cart"></i>
<span class="layout-header-service-cart-num">{{ request.session.shoplist|length}}</span>
</a>
</li>
...
{% extends "web/base.html" %}
{% load static from staticfiles %}
{% block mylink %}
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart-app.css' %}">
{% endblock %}
{% block mainbody %}
<div class="mainbody cart" style="margin-top: 80px;">
<div class="container">
<!-- 购物车详情头 -->
<table class="cart-header">
<tbody>
<tr>
<td class="cart-col-select col-md-3 col-xs-3 col-sm-3">
<div class="cart-select-all JSelectAll">
<div class="mz-checkbox"></div>
<span class="cart-select-title">全选</span>
</div>
</td>
<td class="cart-col-name col-md-3 hidden-xs hidden-sm">商品</td>
<td class="cart-col-price col-md-2 hidden-xs hidden-sm">单价(元)</td>
<td class="cart-col-number col-md-2 hidden-xs hidden-sm">数量</td>
<td class="cart-col-total col-md-1 hidden-xs hidden-sm">小计(元)</td>
<td class="cart-col-ctrl col-md-1 hidden-xs hidden-sm">操作</td>
</tr>
</tbody>
</table><!-- 购物车详情头 E-->
<!-- 购物清单信息列表 -->
<div class="cart-merchant-list">
<div class="cart-merchant">
<table class="cart-merchant-body">
<tbody>
{% for shop in request.session.shoplist.values %}
<tr class="cart-product">
<td class="cart-col-select col-md-3 col-xs-4 col-sm-4">
<div class="mz-checkbox" gid="{{shop.id}}" price="{% widthratio shop.price 1 shop.m %}"></div>
<a href="{% url 'detail' shop.id %}" class="cart-product-link" target="_blank">
<img src="/static/goods/s_{{ shop.picname }}" class="cart-product-img" alt="{{ shop.goods }}" width="50">
</a>
</td>
<td class="cart-col-name col-md-3 col-xs-8 col-sm-8">
<a href="{% url 'detail' shop.id %}" class="cart-product-link" target="_blank">
<p>{{ shop.goods }}</p>
</a>
<p class="">
<span class="cart-product-price">{{ shop.price }}</span>
</p>
<div class="cart-col-number">
<div class="cart-product-number-adder">
<p class="cart-product-number-max show"></p>
<div class="mz-adder">
<button class="mz-adder-subtract disabled"></button>
<div class="mz-adder-num"><input class="mz-adder-input" value="1" type="text"></div>
<button class="mz-adder-add"></button>
</div>
</div>
</div>
</td>
<td class="cart-col-price col-md-2 hidden-xs hidden-sm">
<p>
<span class="cart-product-price">{{ shop.price}}</span>
</p>
</td>
<td class="cart-col-number col-md-2 hidden-xs hidden-sm">
<div class="cart-product-number-adder">
<p class="cart-product-number-max show"></p>
<div class="mz-adder">
<button onclick="window.location='{% url 'cart_change' %}?gid={{shop.id}}&num={{shop.m|add:-1}}'" class="mz-adder-subtract"></button>
<div class="mz-adder-num"><input class="mz-adder-input" value="{{ shop.m }}" onblur="window.location='{% url 'cart_change' %}?gid={{shop.id}}&num='+this.value" type="text"></div>
<button onclick="window.location='{% url 'cart_change' %}?gid={{shop.id}}&num={{shop.m|add:1}}'" class="mz-adder-add"></button>
</div>
</div>
</td>
<td class="cart-col-total col-md-1 hidden-xs hidden-sm">
<span class="cart-product-price total">{% widthratio shop.price 1 shop.m %}</span>
</td>
<td class="cart-col-ctrl col-md-1 hidden-xs hidden-sm">
<a href="{% url 'cart_del' shop.id %}" title="删除">
<div class="cart-product-remove">
<span class="glyphicon glyphicon-remove"></span>
</div>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div><!-- 购物清单信息列表 E-->
</div>
<!-- 结算详情 -->
<div class="cart-footer" id="cartFooter">
<div class="container">
<div class="cart-footer-left col-md-6 col-xs-4 col-sm-4">
<div class="cart-select-all JSelectAll" data-mdesc="全选按钮" data-mtype="store_cart_all">
<div class="mz-checkbox"></div>
<span class="cart-select-title">全选</span>
</div>
<!-- <span class="cart-remove-selected" id="removeSelected">删除选中的商品</span> -->
<span class="cart-footer-count">
共
<span class="cart-footer-num" id="totalCount"></span>
件商品
</span>
<div class="mz-btn btn-danger" onclick="window.location='{% url 'cart_clear' %}'" id="cartSubmit">清空购物车</div>
</div>
<div class="cart-footer-right col-md-5 col-md-offset-1 col-sm-offset-2 col-xs-8 col-sm-6">
<span class="cart-footer-sum">
<span class="cart-footer-text">已优惠</span>
<span class="cart-footer-num red" id="totalDiscount">0.00</span>
<span class="cart-footer-text">元, 合计(不含运费):</span>
<span class="cart-footer-total" id="totalPrice">0.0</span>
</span>
<div onclick="window.location='/orders/add?ids='+loadTotal().join(',')" class="mz-btn btn-success" id="cartSubmit">去结算</div>
</div>
</div>
</div><!-- 结算详情 E-->
</div>
{% endblock %}
{% block myjs %}
//全选
allSelect();
//登录图片鼠标经过
//topLogin();
//商品数量加减
//cartAddMin()
//loadTotal();
var gidlist = [];
{% endblock %}
#在myobject/common/shopmiddleware.py中的__call__()方法中条件如下代码
# ... ...
# 网站前台登录用户判断(订单操作和会员中心操作需登录)
if re.match("^/orders",path) or re.match("^/vip",path):
# 判断当前用户是否没有登录
if "vipuser" not in request.session:
# 执行登录界面跳转
return redirect(reverse('login'))
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
# ... ...
# 订单模型
class Orders(models.Model):
uid = models.IntegerField()
linkman = models.CharField(max_length=32)
address = models.CharField(max_length=255)
code = models.CharField(max_length=6)
phone = models.CharField(max_length=16)
addtime = models.DateTimeField(default=datetime.now)
total = models.FloatField()
state = models.IntegerField()
class Meta:
db_table = "orders" # 更改表名
#订单详情模型
class Detail(models.Model):
orderid = models.IntegerField()
goodsid = models.IntegerField()
name = models.CharField(max_length=32)
price = models.FloatField()
num = models.IntegerField()
class Meta:
db_table = "detail" # 更改表名
在商品购物车页中处理下单按钮,完成向下单操作界面的传值和跳转:
首先将实现准备的topNav.js
替换掉项目中的web/js/topNav.js
<div onclick="window.location='/orders/add?ids='+loadTotal().join(',')" class="mz-btn btn-success" id="cartSubmit">去结算</div>
from django.conf.urls import url
from web.views import index,cart,orders
urlpatterns = [
#网站前台
# ... ...
# 会员及个人中心等路由配置
# ... ...
# 购物车路由
# ... ...
# 订单处理
url(r'^orders/add$', orders.add,name='orders_add'), #订单的表单页
url(r'^orders/confirm$', orders.confirm,name='orders_confirm'), #订单确认页
url(r'^orders/insert$', orders.insert,name='orders_insert'), #执行订单添加操作
]
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from common.models import Goods,Types,Orders,Detail
from datetime import datetime
# 公共信息加载
def loadinfo(request):
'''公共信息加载'''
context = {}
lists = Types.objects.filter(pid=0)
context['typelist'] = lists
return context
def add(request):
'''下订单第一步:订单表单'''
context = loadinfo(request)
# 获取要结算商品的id号
ids = request.GET.get("ids",'')
if len(ids) == 0:
context = {"info":"请选择要结算的商品!"}
return render(request,"web/ordersinfo.html",context)
gidlist = ids.split(',')
# 从购物车获取要结算所有商品,并放入到orderslist中,并且累计总金额
shoplist = request.session['shoplist']
orderslist = {}
total = 0.0
for gid in gidlist:
orderslist[gid] = shoplist[gid]
total += shoplist[gid]['price']*shoplist[gid]['m']
# 将这些信息放入到session中
request.session['orderslist'] = orderslist
request.session['total'] = total
return render(request,"web/ordersadd.html",context)
def confirm(request):
context = loadinfo(request)
return render(request,"web/ordersconfirm.html",context)
def insert(request):
context = loadinfo(request)
try:
# 执行订单信息添加操作
od = Orders()
od.uid = request.session['vipuser']['id'] #当前登录者的id号
od.linkman = request.POST.get('linkman')
od.address = request.POST.get('address')
od.code = request.POST.get('code')
od.phone = request.POST.get('phone')
od.addtime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
od.total = request.session['total']
od.state = 0
od.save()
# 执行订单详情添加
orderslist = request.session['orderslist']
shoplist = request.session['shoplist']
for shop in orderslist.values():
del shoplist[str(shop['id'])]
ov = Detail()
ov.orderid = od.id
ov.goodsid = shop['id']
ov.name = shop['goods']
ov.price = shop['price']
ov.num = shop['m']
ov.save()
del request.session['orderslist']
del request.session['total']
request.session['shoplist'] = shoplist
context = {"info":"订单添加成功!订单号:"+str(od.id)}
return render(request,"web/ordersinfo.html",context)
except Exception as err:
print(err)
context = {"info":"订单添加失败,请稍后再试!"}
return render(request,"web/ordersinfo.html",context)
{% extends "web/base.html" %}
{% load static from staticfiles %}
{% block mylink %}
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart-app.css' %}">
{% endblock %}
{% block mainbody %}
<div class="mainbody cart" style="margin-top: 80px;">
<div class="container">
<!-- 购物车详情头 -->
<table class="cart-header">
<tbody>
<tr>
<td class="cart-col-select col-md-3 col-xs-3 col-sm-3">
<div class="cart-select-all JSelectAll">
<div class="mz-checkbox"></div>
<span class="cart-select-title">全选</span>
</div>
</td>
<td class="cart-col-name col-md-3 hidden-xs hidden-sm">商品</td>
<td class="cart-col-price col-md-2 hidden-xs hidden-sm">单价(元)</td>
<td class="cart-col-number col-md-2 hidden-xs hidden-sm">数量</td>
<td class="cart-col-total col-md-1 hidden-xs hidden-sm">小计(元)</td>
<td class="cart-col-ctrl col-md-1 hidden-xs hidden-sm">操作</td>
</tr>
</tbody>
</table><!-- 购物车详情头 E-->
<!-- 购物清单信息列表 -->
<div class="cart-merchant-list">
<div class="cart-merchant">
<table class="cart-merchant-body">
<tbody>
{% for shop in request.session.shoplist.values %}
<tr class="cart-product">
<td class="cart-col-select col-md-3 col-xs-4 col-sm-4">
<div class="mz-checkbox" gid="{{shop.id}}" price="{% widthratio shop.price 1 shop.m %}"></div>
<a href="{% url 'detail' shop.id %}" class="cart-product-link" target="_blank">
<img src="/static/goods/s_{{ shop.picname }}" class="cart-product-img" alt="{{ shop.goods }}" width="50">
</a>
</td>
<td class="cart-col-name col-md-3 col-xs-8 col-sm-8">
<a href="{% url 'detail' shop.id %}" class="cart-product-link" target="_blank">
<p>{{ shop.goods }}</p>
</a>
<p class="">
<span class="cart-product-price">{{ shop.price }}</span>
</p>
<div class="cart-col-number">
<div class="cart-product-number-adder">
<p class="cart-product-number-max show"></p>
<div class="mz-adder">
<button class="mz-adder-subtract disabled"></button>
<div class="mz-adder-num"><input class="mz-adder-input" value="1" type="text"></div>
<button class="mz-adder-add"></button>
</div>
</div>
</div>
</td>
<td class="cart-col-price col-md-2 hidden-xs hidden-sm">
<p>
<span class="cart-product-price">{{ shop.price}}</span>
</p>
</td>
<td class="cart-col-number col-md-2 hidden-xs hidden-sm">
<div class="cart-product-number-adder">
<p class="cart-product-number-max show"></p>
<div class="mz-adder">
<button onclick="window.location='{% url 'cart_change' %}?gid={{shop.id}}&num={{shop.m|add:-1}}'" class="mz-adder-subtract"></button>
<div class="mz-adder-num"><input class="mz-adder-input" value="{{ shop.m }}" onblur="window.location='{% url 'cart_change' %}?gid={{shop.id}}&num='+this.value" type="text"></div>
<button onclick="window.location='{% url 'cart_change' %}?gid={{shop.id}}&num={{shop.m|add:1}}'" class="mz-adder-add"></button>
</div>
</div>
</td>
<td class="cart-col-total col-md-1 hidden-xs hidden-sm">
<span class="cart-product-price total">{% widthratio shop.price 1 shop.m %}</span>
</td>
<td class="cart-col-ctrl col-md-1 hidden-xs hidden-sm">
<a href="{% url 'cart_del' shop.id %}" title="删除">
<div class="cart-product-remove">
<span class="glyphicon glyphicon-remove"></span>
</div>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div><!-- 购物清单信息列表 E-->
</div>
<!-- 结算详情 -->
<div class="cart-footer" id="cartFooter">
<div class="container">
<div class="cart-footer-left col-md-6 col-xs-4 col-sm-4">
<div class="cart-select-all JSelectAll" data-mdesc="全选按钮" data-mtype="store_cart_all">
<div class="mz-checkbox"></div>
<span class="cart-select-title">全选</span>
</div>
<!-- <span class="cart-remove-selected" id="removeSelected">删除选中的商品</span> -->
<span class="cart-footer-count">
共
<span class="cart-footer-num" id="totalCount"></span>
件商品
</span>
<div class="mz-btn btn-danger" onclick="window.location='{% url 'cart_clear' %}'" id="cartSubmit">清空购物车</div>
</div>
<div class="cart-footer-right col-md-5 col-md-offset-1 col-sm-offset-2 col-xs-8 col-sm-6">
<span class="cart-footer-sum">
<span class="cart-footer-text">已优惠</span>
<span class="cart-footer-num red" id="totalDiscount">0.00</span>
<span class="cart-footer-text">元, 合计(不含运费):</span>
<span class="cart-footer-total" id="totalPrice">0.0</span>
</span>
<div onclick="window.location='/orders/add?ids='+loadTotal().join(',')" class="mz-btn btn-success" id="cartSubmit">去结算</div>
</div>
</div>
</div><!-- 结算详情 E-->
</div>
{% endblock %}
{% block myjs %}
//全选
allSelect();
//登录图片鼠标经过
//topLogin();
//商品数量加减
//cartAddMin()
loadTotal();
var gidlist = [];
{% endblock %}
{% extends "web/base.html" %}
{% load static from staticfiles %}
{% block mylink %}
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart-app.css' %}">
{% endblock %}
{% block mainbody %}
<form action="{% url 'orders_confirm' %}" method="post">
{% csrf_token %}
<div class="mainbody cart" style="margin-top: 80px;">
<div class="container">
<!-- 下订单的1/3步骤 -->
<table class="cart-header">
<tbody>
<tr>
<td class="cart-col-select col-md-12">
当前位置: 订单处理 > 1/3 填写收货地址:
</td>
</tr>
</tbody>
</table><!-- 下订单的1/3步骤 E-->
<!-- 订单物流信息 -->
<div class="cart-merchant-list">
<div class="cart-merchant">
<table class="cart-merchant-body">
<tbody>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
联系人:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input type="text" name="linkman" value="{{ request.session.vipuser.name}}" size="40"/>
</td>
</tr>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
收货地址:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input type="text" name="address" value="{{ request.session.vipuser.address}}" size="40"/>
</td>
</tr>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
联系电话:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input type="text" name="phone" value="{{ request.session.vipuser.phone}}" size="40"/>
</td>
</tr>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
邮编:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input type="text" name="code" value="{{ request.session.vipuser.code}}" size="40"/>
</td>
</tr>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
总金额:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input type="text" disabled value="{{ request.session.total }} 元" name="linkman" size="40"/>
</td>
</tr>
</tbody>
</table>
</div>
</div><!-- 订单物流信息 E-->
</div>
<!-- 操作按钮 -->
<div class="cart-footer" id="cartFooter">
<div class="container">
<div class="cart-footer-right col-md-12" style="text-align:center">
<div onclick="window.history.go(-1)" class="mz-btn btn-success" id="cartSubmit">返回</div>
<button type="submit" class="mz-btn btn-success" id="cartSubmit">下一步</button>
</div>
</div>
</div><!-- 操作按钮 E-->
</div></form>
{% endblock %}
{% extends "web/base.html" %}
{% load static from staticfiles %}
{% block mylink %}
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart-app.css' %}">
{% endblock %}
{% block mainbody %}
<form action="{% url 'orders_insert' %}" method="post">
{% csrf_token %}
<div class="mainbody cart" style="margin-top: 80px;padding-bottom:5px;">
<div class="container">
<!-- 下订单的2/3步骤 -->
<table class="cart-header">
<tbody>
<tr>
<td class="cart-col-select col-md-12">
当前位置: 订单处理 > 2/3 确认订单信息:
</td>
</tr>
</tbody>
</table><!-- 下订单的2/3步骤 E-->
<!-- 订单通信信息 -->
<div class="cart-merchant-list">
<div class="cart-merchant">
<table class="cart-merchant-body">
<tbody>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
联系人:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input readonly type="text" name="linkman" value="{{ request.POST.linkman}}" size="40"/>
</td>
</tr>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
收货地址:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input readonly type="text" name="address" value="{{ request.POST.address}}" size="40"/>
</td>
</tr>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
联系电话:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input readonly type="text" name="phone" value="{{ request.POST.phone}}" size="40"/>
</td>
</tr>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
邮编:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input readonly type="text" name="code" value="{{ request.POST.code}}" size="40"/>
</td>
</tr>
<tr class="cart-product" style="height:60px;border:none;">
<td class="cart-col-select col-md-2 col-xs-3 col-sm-3" style="text-align: right;">
总金额:
</td>
<td class="cart-col-name col-md-3 col-xs-4 col-sm-4">
<input type="text" disabled value="{{ request.session.total }} 元" name="linkman" size="40"/>
</td>
</tr>
</tbody>
</table>
</div>
</div><!-- 订单通信信息 E-->
</div>
<!-- 操作按钮 -->
<div class="cart-footer" id="cartFooter">
<div class="container">
<div class="cart-footer-right col-md-12" style="text-align:center">
<div onclick="window.history.go(-1)" class="mz-btn btn-success" id="cartSubmit">返回修改</div>
<button type="submit" class="mz-btn btn-success" id="cartSubmit">确认下单</button>
</div>
</div>
</div><!-- 操作按钮 E-->
</div></form>
<div class="mainbody cart" style="padding-bottom:15px;">
<div class="container">
<!-- 订单信息头 -->
<table class="cart-header">
<tbody>
<tr>
<td class="cart-col-name col-md-3 hidden-xs hidden-sm">商品</td>
<td class="cart-col-name col-md-3 hidden-xs hidden-sm">图片</td>
<td class="cart-col-price col-md-2 hidden-xs hidden-sm">单价(元)</td>
<td class="cart-col-number col-md-2 hidden-xs hidden-sm">数量</td>
<td class="cart-col-total col-md-1 hidden-xs hidden-sm">小计(元)</td>
</tr>
</tbody>
</table><!-- 订单信息头 E-->
<!-- 订单确认信息 -->
<div class="cart-merchant-list">
<div class="cart-merchant">
<table class="cart-merchant-body">
<tbody>
{% for shop in request.session.orderslist.values %}
<tr class="cart-product" style="height:100px;">
<td class="cart-col-name col-md-3 hidden-xs hidden-sm">
<p>
<div class="mz-adder-num">{{ shop.goods }}</div>
</p>
</td>
<td class="cart-col-name col-md-3 hidden-xs hidden-sm">
<p>
<div class="mz-adder-num"><img src="/static/goods/s_{{ shop.picname }}" alt="{{ shop.goods }}" width="50"></div>
</p>
</td>
<td class="cart-col-price col-md-2 hidden-xs hidden-sm">
<p>
<span class="cart-product-price">{{ shop.price}}</span>
</p>
</td>
<td class="cart-col-number col-md-2 hidden-xs hidden-sm">
<p>
<div class="mz-adder-num">{{ shop.m }}</div>
</p>
</td>
<td class="cart-col-total col-md-1 hidden-xs hidden-sm">
<span class="cart-product-price total">{% widthratio shop.price 1 shop.m %}</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div><!-- 订单确认信息 E-->
</div>
</div>
{% endblock %}
{% extends "web/base.html" %}
{% load static from staticfiles %}
{% block mylink %}
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'web/css/cart-app.css' %}">
{% endblock %}
{% block mainbody %}
<div class="mainbody cart" style="margin-top: 80px;">
<div class="container">
<!-- 下订单的3/3步骤 -->
<table class="cart-header">
<tbody>
<tr>
<td class="cart-col-select col-md-12">
当前位置: 订单处理 > 3/3 订单完成:
</td>
</tr>
</tbody>
</table><!-- 下订单的3/3步骤 E-->
<!-- 下订单提示信息 -->
<div class="cart-merchant-list">
<div class="cart-merchant text-center" style="font-size:30px;color:#fc0;line-height:100px;">
{{ info }}
</div>
</div><!-- 下订单提示信息 E-->
</div>
<!-- 操作按钮 -->
<div class="cart-footer" id="cartFooter">
<div class="container">
<div class="cart-footer-right col-md-12" style="text-align:center">
<div onclick="window.history.go(-1)" class="mz-btn btn-success" id="cartSubmit">返回</div>
<a href="{% url 'index' %}" class="mz-btn btn-success">首页</a>
</div>
</div>
</div><!-- 操作按钮 E-->
</div>
{% endblock %}
from django.conf.urls import url
from web.views import index,cart,orders,vip
urlpatterns = [
#网站前台
# ... ...
# 会员及个人中心等路由配置
# ... ...
# 购物车路由
# ... ...
# 订单处理
# ... ...
# 会员中心
url(r'^vip/orders$', vip.viporders,name='vip_orders'), #会员中心我的订单
url(r'^vip/odstate$', vip.odstate,name='vip_odstate'), #修改订单状态(确认收货)
#url(r'^vip/info$', vip.info,name='vip_info'), #会员中心的个人信息
#url(r'^vip/update$', vip.update,name='vip_update'), #执行修改会员信息
#url(r'^vip/resetps$', vip.resetps,name='vip_resetps'), #重置密码表单
#url(r'^vip/doresetps$', vip.doresetps,name='vip_doresetps'), #执行重置密码
]
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from common.models import Users,Goods,Types,Orders,Detail
# 公共信息加载
def loadinfo(request):
'''公共信息加载'''
context = {}
lists = Types.objects.filter(pid=0)
context['typelist'] = lists
return context
# 我的订单
def viporders(request):
'''当前用户订单'''
context = loadinfo(request)
# 获取当前用户的所有订单信息
odlist = Orders.objects.filter(uid=request.session['vipuser']['id'])
# 遍历当前用户的所有订单,添加他的订单详情
for od in odlist:
delist = Detail.objects.filter(orderid=od.id)
# 遍历每个商品详情,从Goods中获取对应的图片
for og in delist:
og.picname = Goods.objects.only('picname').get(id=og.goodsid).picname
od.detaillist = delist
# 将整理好的订单信息放置到模板遍历中
context['orderslist'] = odlist
return render(request,"web/viporders.html",context)
def odstate(request):
''' 修改订单状态 '''
try:
oid = request.GET.get("oid",'0')
ob = Orders.objects.get(id=oid)
ob.state = request.GET['state']
ob.save()
return redirect(reverse('vip_orders'))
except Exception as err:
print(err)
return HttpResponse("订单处理失败!")
{% extends "web/base.html" %}
{% load static from staticfiles %}
{% block mylink %}
<link rel="stylesheet" type="text/css" href="{% static 'web/css/order.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'web/css/order-app.css' %}">
{% endblock %}
{% block mainbody %}
<div class="mainbody order">
<div class="container">
<!-- 面包屑导航 -->
<div class="crumbs col-xs-12 col-sm-12">
<ol class="breadcrumb">
<li class="hidden-xs hidden-sm"><a href="index.html">首页</a></li>
<li class="hidden-xs hidden-sm"><a href="member.html">我的商城</a></li>
<li class="active">我的订单</li>
</ol>
</div><!-- 面包屑导航 E-->
<div class="main clearfix">
<!-- 左侧导航 -->
<div class="left-nav f-fl col-md-4 hidden-xs hidden-sm">
<div class="nav-main">
<a href="javascript:;" class="type-title"><span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span>订单中心</a>
<a href="order.html" class="ml active" >我的订单</a>
<a href="#" class="ml " >我的回购单</a>
<a href="#" class="ml " >我的意外保</a>
<a href="javascript:;" class="type-title"><span class="glyphicon glyphicon-user" aria-hidden="true"></span>个人中心</a>
<a href="/#" class="ml " >地址管理</a>
<a href="#" class="ml " >我的收藏</a>
<a href="#" class="ml " >消息提醒</a>
<a href="#" class="ml " >建议反馈</a>
</div>
</div><!-- 左侧导航 E-->
<!-- 右侧内容展示 -->
<div class="right-content f-fr col-md-8 col-xs-12 col-sm-12">
<div class="order-main">
<div class="type-tab-btn">
<a href="javascript:;" class="allOrder active col-20" data-type="-1">全部订单</a><i class="line hidden-xs hidden-sm">|</i>
<a class="waitPay col-20" href="javascript:;" data-type="0">待付款<span class="amount _actAmount"></span></a><i class="line hidden-xs hidden-sm">|</i>
<a class="waitDeliver col-20" href="javascript:;" data-type="1">待发货</a><i class="line hidden-xs hidden-sm">|</i>
<a class="hasDeliver col-20" href="javascript:;" data-type="2">已发货</a><i class="line hidden-xs hidden-sm">|</i>
<a class="other col-20" href="javascript:;" data-type="99">其他</a>
</div>
<div class="list-head hidden-xs hidden-sm">
<ul class="clearfix">
<li class="w50">
<select id="checkType" class="check-type">
<option value="0">近三个月的订单</option>
<option value="1">全部订单</option>
</select>
订单明细
</li>
<li class="w125">售后</li>
<li class="w125">金额</li>
<li class="w125">状态</li>
<li class="w125">操作</li>
</ul>
</div>
<div id="tableList" class="type-contain ui-load-container">
<!-- 每个订单信息 -->
{% for orders in orderslist %}
<div class="ui-load-content" style="margin-top: 20px">
<table class="orderItem">
<tbody>
<tr class="trHead hidden-xs hidden-sm">
<td colspan="4" class="title clearfix">
<div class="f-fl">
订单号:<span class="time">201700{{ orders.id }}</span>
收货人:<span class="orderNumber">{{ orders.linkman }}</span>
收货地址:<span class="orderNumber">{{ orders.address }}</span>
联系电话:<span class="orderNumber">{{ orders.phone }}</span>
</div>
</td>
</tr>
<tr class="list-box b-l b-r b-b">
<td class="list b-r j-iamCart">
<div class="cart-wrap j-CartWrap">
<div class="shop j-shop j-amLight">
{% for detail in orders.detaillist %}
<div class="item b-t clearfix j-item j-iamMain" style="height:110px;">
<a class="productDetail nameWidth col-xs-4 col-sm-4" href="{% url 'detail' detail.goodsid %}" target="_blank">
<img src="/static/goods/s_{{detail.picname}}" style="width:75px;height:75px" class="f-fl"/>
</a>
<div class="describe f-fl col-xs-8 col-sm-8">
<div class="vertic clearfix">
<span class="clearfix">
<a class="productDetail nameWidth" href="#" target="_blank">
<i>{{ detail.name }}</i></a>
<p>
¥{{ detail.price}}×{{ detail.num}}
</p>
</span>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</td>
<td class="b-r w125 center price b-t hidden-xs hidden-sm">
<div class="priceDiv">
¥ {{ orders.total }} 元
</div>
</td>
<td class="b-r w125 center state b-t hidden-xs hidden-sm">
<div class="stateDiv">
<div>
{% if orders.state == 0 %}
新订单 <br/><br/><br/>
【<a href="{% url 'vip_odstate' %}?oid={{orders.id}}&state=3">撤销订单</a>】
{% elif orders.state == 1 %}
已发货 <br/><br/>
【<a href="{% url 'vip_odstate' %}?oid={{orders.id}}&state=2">确认收货</a>】
{% elif orders.state == 2 %}
已完成
{% elif orders.state == 3 %}
无效订单
{% else %}
未知
{% endif %}
</div>
</div>
</td>
<td class="w125 center opreat b-t hidden-xs hidden-sm">
<ul>
<li class="more"><a href="#" target="_blank">查看详情</a></li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
{% endfor %}
<!-- 每个订单信息 end-->
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 主内容区域 E-->
{% endblock %}
from django.conf.urls import url
from myadmin.views import index,users,type,goods,orders
urlpatterns = [
...
# 订单信息管理路由
url(r'^orders$', orders.index, name="myadmin_orders_index"),
url(r'^orders/(?P<pIndex>[0-9]+)$', orders.index, name="myadmin_orders_index"),
url(r'^orders/detail/(?P<oid>[0-9]+)$', orders.detail, name="myadmin_orders_detail"),
url(r'^orders/state$',orders.state, name="myadmin_orders_state"),
]
from django.shortcuts import render
from django.http import HttpResponse
from django.db.models import Q
from django.core.paginator import Paginator
from common.models import Goods,Users,Orders,Detail
# Create your views here.
def index(request,pIndex=1):
'''浏览信息'''
#获取订单信息
mod = Orders.objects
mywhere=[]
# 获取、判断并封装关keyword键搜索
kw = request.GET.get("keyword",None)
if kw:
# 查询收件人和地址中只要含有关键字的都可以
list = mod.filter(Q(linkman_contains=kw) | Q(address__contains=kw))
mywhere.append("keyword="+kw)
else:
list = mod.filter()
# 获取、判断并封装订单状态state搜索条件
state = request.GET.get('state','')
if state != '':
list = list.filter(state=state)
mywhere.append("state="+state)
#执行分页处理
pIndex = int(pIndex)
page = Paginator(list,5) #以5条每页创建分页对象
maxpages = page.num_pages #最大页数
#判断页数是否越界
if pIndex > maxpages:
pIndex = maxpages
if pIndex < 1:
pIndex = 1
list2 = page.page(pIndex) #当前页数据
plist = page.page_range #页码数列表
# 遍历订单信息并追加 下订单人姓名信息
for od in list2:
user = Users.objects.only('name').get(id=od.uid)
od.name = user.name
#封装信息加载模板输出
context = {"orderslist":list2,'plist':plist,'pIndex':pIndex,'maxpages':maxpages,'mywhere':mywhere}
return render(request,"myadmin/orders/index.html",context)
def detail(request,oid):
''' 订单详情信息 '''
try:
# 加载订单信息
orders = Orders.objects.get(id=oid)
if orders != None:
user = Users.objects.only('name').get(id=orders.uid)
orders.name = user.name
# 加载订单详情
dlist = Detail.objects.filter(orderid=oid)
# 遍历每个商品详情,从Goods中获取对应的图片
for og in dlist:
og.picname = Goods.objects.only('picname').get(id=og.goodsid).picname
# 放置模板变量,加载模板并输出
context = {'orders':orders,'detaillist':dlist}
return render(request,"myadmin/orders/detail.html",context)
except Exception as err:
print(err)
context = {'info':'没有找到要修改的信息!'}
return render(request,"myadmin/info.html",context)
def state(request):
''' 修改订单状态 '''
try:
oid = request.GET.get("oid",'0')
ob = Orders.objects.get(id=oid)
ob.state = request.GET['state']
ob.save()
context = {'info':'修改成功!'}
except Exception as err:
print(err)
context = {'info':'修改失败!'}
return render(request,"myadmin/info.html",context)
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h4>
订单信息管理
</h4>
<form class="form-inline" action="{% url 'myadmin_orders_index'%}" method="get">
<label>关键字:</label>
<input type="text" name="keyword" value="{{request.GET.keyword}}" class="input-small" placeholder="收货人或地址"/>
<label> 状态:</label>
<select name="state" class="span1" style="width:100px;">
<option value="">全部</option>
<option value="1" {% if request.GET.state == '0' %}selected{% endif %}>未发货</option>
<option value="1" {% if request.GET.state == '1' %}selected{% endif %}>已发货</option>
<option value="2" {% if request.GET.state == '2' %}selected{% endif %}>已完成</option>
<option value="3" {% if request.GET.state == '3' %}selected{% endif %}>已作废</option>
</select>
<button type="submit" class="btn">搜索</button>
<a href="{% url 'myadmin_goods_index' 1 %}" class="btn">全部</a>
</form>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>订单号</th>
<th>下单人</th>
<th>收货人</th>
<th>收货地址</th>
<th>联系电话</th>
<th>时间</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for vo in orderslist %}
<tr>
<td>{{ vo.id }}</td>
<td>{{ vo.name }}</td>
<td>{{ vo.linkman }}</td>
<td>{{ vo.address }}</td>
<td>{{ vo.phone }}</td>
<td>{{ vo.addtime|date:'Y-m-d H:i:s' }}</td>
<td>
{% if vo.state == 0 %}
新订单
{% elif vo.state == 1 %}
已发货
{% elif vo.state == 2 %}
已完成
{% elif vo.state == 3 %}
无效订单
{% else %}
未知
{% endif %}</td>
<td>
<a href="{% url 'myadmin_orders_detail' vo.id %}" class="view-link">查看详情</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<ul>
<li>
<a href="{% url 'myadmin_orders_index' pIndex|add:-1 %}?{{ mywhere|join:'&' }}">«</a>
</li>
{% for p in plist %}
<li {% if pIndex == p %}class="active"{% endif %}>
<a href="{% url 'myadmin_orders_index' p %}?{{ mywhere|join:'&' }}">{{p}}</a>
</li>
{% endfor %}
<li>
<a href="{% url 'myadmin_orders_index' pIndex|add:1 %}?{{ mywhere|join:'&' }}">»</a>
</li>
</ul>
</div>
{% endblock %}
{% extends "myadmin/base.html" %}
{% block mainbody %}
<h4>
订单信息:
</h4>
<table class="table table-bordered">
<tr>
<th width="12%" style="text-align:right;background-color:#eee;">订单号:</th>
<td width="25%">201700{{ orders.id }}</td>
<th width="12%" style="text-align:right;background-color:#eee;">下单人:</th>
<td width="51%">{{ orders.name }}</td>
</tr>
<tr>
<th style="text-align:right;background-color:#eee;">收货人:</th>
<td>{{ orders.linkman }}</td>
<th style="text-align:right;background-color:#eee;">订单地址:</th>
<td>{{ orders.address }}</td>
</tr>
<tr>
<th style="text-align:right;background-color:#eee;">邮政编码:</th>
<td>{{ orders.code }}</td>
<th style="text-align:right;background-color:#eee;">下单时间:</th>
<td>{{ orders.addtime }}</td>
</tr>
<tr>
<th style="text-align:right;background-color:#eee;">总计金额:</th>
<td>{{ orders.total }}</td>
<th style="text-align:right;background-color:#eee;">订单状态:</th>
<td>
{% if orders.state == 0 %}
新订单 【<a href="{% url 'myadmin_orders_state' %}?oid={{orders.id}}&state=1">确认发货</a>】
【<a href="{% url 'myadmin_orders_state' %}?oid={{orders.id}}&state=3">订单作废</a>】
{% elif orders.state == 1 %}
已发货
{% elif orders.state == 2 %}
已完成
{% elif orders.state == 3 %}
无效订单
{% else %}
未知
{% endif %}
</td>
</tr>
</table>
<br/>
<h4>
订单详情信息:
</h4>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>id号</th>
<th>图片</th>
<th>商品名称</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
</tr>
</thead>
<tbody>
{% for vo in detaillist %}
<tr>
<td>{{ vo.id }}</td>
<td><img src="/static/goods/s_{{ vo.picname }}" width="35" /></td>
<td>{{ vo.name }}</td>
<td>{{ vo.price }}</td>
<td>{{ vo.num }}</td>
<td>{{ vo.price }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div style="text-align:center">
<button onclick="window.history.back()">返回</button>
<button >打印订单</button>
</div>
{% endblock %}
1 本次项目完成的模块介绍: