本规定对一个完整的开发过程按“软件过程改进方法和规范”把
产品生命周期
划分为 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','[email protected]',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 %}
<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">
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 Toura>
li>
<li>
<a href="help.htm">Project Organisationa>
li>
<li>
<a href="help.htm">Task Assignmenta>
li>
<li>
<a href="help.htm">Access Permissionsa>
li>
<li class="divider">
li>
<li class="nav-header">
Files
li>
<li>
<a href="help.htm">How to upload multiple filesa>
li>
<li>
<a href="help.htm">Using file versiona>
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> Helpa>
li>
<li class="nav-header">
Bonus Templates
li>
<li>
<a href="gallery.htm"><i class="icon-picture">i> Gallerya>
li>
<li>
<a href="blank.htm"><i class="icon-stop">i> Blank Slatea>
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 Toura> <a class="btn btn-large">No Thanksa>
p>
div>
<div class="well summary">
<ul>
<li>
<a href="#"><span class="count">3span> Projectsa>
li>
<li>
<a href="#"><span class="count">27span> Tasksa>
li>
<li>
<a href="#"><span class="count">7span> Messagesa>
li>
<li class="last">
<a href="#"><span class="count">5span> Filesa>
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[0-9]+)$' , users.delete, name="myadmin_users_del"),
url(r'^users/edit/(?P[0-9]+)$' , users.edit, name="myadmin_users_edit"),
url(r'^users/update/(?P[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="#">1a>
li>
<li>
<a href="#">2a>
li>
<li>
<a href="#">3a>
li>
<li>
<a href="#">4a>
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">
男
女
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">
管理员
启用会员
禁用用户
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 %}
<html lang="cn">
<head>
<meta charset="utf-8">
<title>Login - Akiratitle>
<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">
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 %}
<html lang="cn">
<head>
<meta charset="utf-8">
<title>Login - Akiratitle>
<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">
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[0-9]+)$' , type.add, name="myadmin_type_add"),
url(r'^type/insert$', type.insert, name="myadmin_type_insert"),
url(r'^type/del/(?P[0-9]+)$' , type.delete, name="myadmin_type_del"),
url(r'^type/edit/(?P[0-9]+)$' , type.edit, name="myadmin_type_edit"),
url(r'^type/update/(?P[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>父类别idth>
<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="#">1a>
li>
<li>
<a href="#">2a>
li>
<li>
<a href="#">3a>
li>
<li>
<a href="#">4a>
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[0-9]+)$' , goods.delete, name="myadmin_goods_del"),
url(r'^goods/edit/(?P[0-9]+)$' , goods.edit, name="myadmin_goods_edit"),
url(r'^goods/update/(?P[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="#">1a>
li>
<li>
<a href="#">2a>
li>
<li>
<a href="#">3a>
li>
<li>
<a href="#">4a>
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 %}
{% 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 %}
[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[0-9]+)$', ... ... ),
,具体如下:from django.conf.urls import url
from myadmin.views import index,users,type,goods
urlpatterns = [
...
# 后台商品信息管理
url(r'^goods/(?P[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[0-9]+)$' , goods.delete, name="myadmin_goods_del"),
url(r'^goods/edit/(?P[0-9]+)$' , goods.edit, name="myadmin_goods_edit"),
url(r'^goods/update/(?P[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 %}
/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[0-9]+)$' , index.lists, name="list"),# 商品列表
url(r'^detail/(?P[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[0-9]+)$' , cart.add, name="cart_add"),
url(r'^cart/del/(?P[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[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[0-9]+)$',index.lists,name="list"), #分页商品列表展示
url(r'^detail/(?P[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 %}
<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">
<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">
<link href="{% static 'web/css/bootstrap.min.css' %}" rel="stylesheet">
<script src="{% static 'web/js/jquery-1.12.4.min.js' %}">script>
<script src="{% static 'web/js/bootstrap.min.js' %}">script>
<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>
<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 密码:123span>
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>
div>
div>
<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">Englisha>
div>
div>
div>
<div class="footer-service">
<span class="service-label">客服热线span>
<span class="service-num">400-888-6666span>
<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号-4a>
<a href="#" class="linkAGray" target="_blank">经营许可证编号: 京A1-20280198a>
<a target="_blank" href="#" class="linkAGray">营业执照a>
div>
div>
div>
div>
<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[0-9]+)$',index.lists,name="list"), #分页商品列表展示
url(r'^detail/(?P[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">
<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>
<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 %}
<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[0-9]+)$' , cart.add,name='cart_add'), #添加购物车
url(r'^cart/del/(?P[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>
<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>
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-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.00span>
<span class="cart-footer-text">元, 合计(不含运费):span>
<span class="cart-footer-total" id="totalPrice">0.0span>
span>
<div onclick="window.location='/orders/add?ids='+loadTotal().join(',')" class="mz-btn btn-success" id="cartSubmit">去结算div>
div>
div>
div>
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>
<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>
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-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.00span>
<span class="cart-footer-text">元, 合计(不含运费):span>
<span class="cart-footer-total" id="totalPrice">0.0span>
span>
<div onclick="window.location='/orders/add?ids='+loadTotal().join(',')" class="mz-btn btn-success" id="cartSubmit">去结算div>
div>
div>
div>
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">
<table class="cart-header">
<tbody>
<tr>
<td class="cart-col-select col-md-12">
当前位置: 订单处理 > 1/3 填写收货地址:
td>
tr>
tbody>
table>
<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>
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>
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">
<table class="cart-header">
<tbody>
<tr>
<td class="cart-col-select col-md-12">
当前位置: 订单处理 > 2/3 确认订单信息:
td>
tr>
tbody>
table>
<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>
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>
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>
<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>
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">
<table class="cart-header">
<tbody>
<tr>
<td class="cart-col-select col-md-12">
当前位置: 订单处理 > 3/3 订单完成:
td>
tr>
tbody>
table>
<div class="cart-merchant-list">
<div class="cart-merchant text-center" style="font-size:30px;color:#fc0;line-height:100px;">
{
{ info }}
div>
div>
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>
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<