Django-web项目(全过程 文末附源码 +Xmind笔记)

XX商城

XX商城........................................................................ 1

1.     项目需求分析...................................................... 6

1.1.     概念............................................................... 6

1.1.1.      原因...................................................... 6

1.1.2.      方式...................................................... 6

1.1.3.      内容...................................................... 6

1.1.4.      结果...................................................... 6

1.2.     页面|业务逻辑............................................. 6

1.2.1.      注册........................................................ 6

1.2.2.      登陆........................................................ 6

1.2.3.      首页........................................................ 6

1.2.4.      商品搜索................................................ 6

1.2.5.      商品列表................................................ 6

1.2.6.      商品详情页............................................ 6

1.2.7.      个人信息................................................ 6

1.2.8.      购物车.................................................... 6

1.2.9.      订单页.................................................... 6

1.2.10.        收货地址............................................ 6

1.2.11.        订单的确认........................................ 6

1.2.12.        提交订单............................................ 7

1.2.13.        支付宝支付........................................ 7

1.2.14.        支付宝处理结果................................ 7

1.2.15.        商品评价............................................ 7

1.3.     划分模块  | 功能....................................... 7

1.3.1.      用户..................................................  7

1.3.2.      验证.................................................... 7

1.3.3.      第三方登陆...................................... 7

1.3.4.      首页广告......................................... 7

1.3.5.      商品 ............................................... 7

1.3.6.      购物车...............................................7

1.3.7.      订单 ................................................. 7

1.3.8.      支付 ................................................... 7

1.3.9.      MIS系统.............................................. 7

2.      架构设计.............................................................. 7

2.1.     开发模式.......................................................... 7

2.2.     后端框架......................................................... 8

2.2.1.      页面的整体刷新...................................... 8

2.3.     前端框架........................................................ 8

2.3.1.      页面的局部刷新...................................... 8

2.4.     部分静态化..................................................... 8

2.5.     Nginx............................................................. 8

2.6.     uwsgi............................................................ 8

3.      工程创建和配置.................................................. 8

3.1.     创建仓库....................................................... 8

3.1.1.      在gitee中创建项目............................. 8

3.1.2.      新建 .gitignore文件............................. 8

3.1.3.      新建分支................................................ 9

3.1.4.      克隆仓库................................................ 9

3.1.5.      在仓库里克隆公用分支........................ 9

3.1.6.      在仓库里新建本地分支........................ 9

3.1.7.      [git回顾]  配置ssh公钥.................... 9

3.2.     创建项目..................................................... 10

3.2.1.      使用django虚拟环境........................ 10

3.2.2.      pycharm ............................... 10

3.2.4.      设置配置信息.......................... 10

3.3.     配置............................................................. 10

3.3.1.      1、修改配置文件................................ 10

3.3.2.      2、jinja2............................................... 11

3.3.3.      3、MySQL数据库............................... 12

3.3.4.      4、Redis数据库  读写速度快.......... 14

3.3.5.      5、日志................................................ 15

3.3.6.      6、静态文件........................................ 17

4.      目录结构............................................................ 17

4.1.     logs.............................................................. 17

4.2.     manage.py................................................... 18

4.3.     工程同名文件............................................. 18

4.3.1.      setting.................................................. 18

4.3.2.      static..................................................... 18

4.3.3.      templates............................................. 18

4.3.4.      utils....................................................... 18

4.3.5.      libs........................................................ 18

4.3.6.      apps...................................................... 18

4.3.7.      __init__.py........................................... 18

4.3.8.      urls.py................................................... 18

4.3.9.      wsgi.py................................................. 18

5.      模块功能实现.................................................... 18

5.1.     用户注册..................................................... 18

5.1.1.      展示用户注册页面.............................. 19

5.1.2.      用户模型类.......................................... 20

5.1.3.      业务实现.............................................. 21

5.2.     验证码......................................................... 25

5.2.1.      图形验证码.......................................... 25

5.2.2.      短信验证码.......................................... 27

5.2.3.      优化...................................................... 30

5.2.4.      异步方案.............................................. 31

5.3.     用户登陆..................................................... 33

5.3.1.      账号登陆.............................................. 33

5.3.2.      QQ登陆............................................... 35

5.4.     用户中心..................................................... 37

5.4.1.      用户基本信息...................................... 37

5.4.2.      添加和验证邮箱.................................. 37

5.4.3.      收货地址.............................................. 40

5.4.4.      修改密码.............................................. 40

5.5.     商品............................................................. 40

5.5.1.      商品数据库表的设计.......................... 41

5.5.2.      准备商品数据...................................... 41

5.5.3.      首页广告.............................................. 41

5.5.4.      商品列表页.......................................... 41

5.5.5.      商品搜索.............................................. 41

5.5.6.      商品详情页.......................................... 41

5.5.7.      用户浏览记录...................................... 41

5.6.     购物车......................................................... 41

6.      性能优化............................................................ 41

7.      部署.................................................................... 41

Django WEB 项目

  1. 项目需求分析
    1. 概念
      1. 原因: 需求驱动开发
      2. 方式: 原型图
      3. 内容: 了解页面及业务逻辑,归纳业务模块
      4. 结果:划分业务模块及每个模块下的主要功能
    2. 页面|业务逻辑
      1. 注册
      2. 登陆
      3. 首页

分类、广告位

      1. 商品搜索
      2. 商品列表
      3. 商品详情页
      4. 个人信息
      5. 购物车
      6. 订单页
      7. 收货地址
      8. 订单的确认
      9. 提交订单
      10. 支付宝支付
      11. 支付宝处理结果
      12. 商品评价
    1. 划分模块  | 功能
      1. 用户:注册、登陆、用户中心(基本信息、邮箱激活、收获地址、我的订单、修改密码)
      2. 验证: 图形验证、短信验证
      3. 第三方登陆:QQ登陆
      4. 首页广告 :首页广告
      5. 商品 : 商品列表、商品搜索、商品详情、商品浏览记录
      6. 购物车 : 购物车管理、购物车合并
      7. 订单 : 确认订单、提交订单、订单商品评价
      8. 支付  :支付宝支付
      9. MIS系统 : 数据统计、用户管理 、权限管理、商品管理、订单管理
  1. 架构设计
    1. 开发模式:前后端不分离
      1. SEO
      2. 分离: 前端请求两个服务器。1、前端服务器返回html文件。2、html中的jquery\ajax...发送异步http请求动态数据----->返回json数据局部刷新
      3. 不分离:客户端url 服务器地址正则匹配,找视图,执行视图, render()===>html
    2. 后端框架:Django+jinja2
      1. 页面的整体刷新
    3. 前端框架:vue.js
      1. 页面的局部刷新
    4. 部分静态化:增加效率
    5. Nginx:代理服务器
    6. uwsgi:服务器
      1. 实现了wsgi协议的一款软件
      2. 正式阶段使用,替代了开发服务器
      3. 开发服务器:python manage.py runserver
  2. 工程创建和配置
    1. 创建仓库
      1. 在gitee中创建项目

[修改README文件]

      1. 新建 .gitignore文件

该文件中的文件不会被git add管理

.ideal/

*.pyc

公用

      1. 克隆仓库

git clone

      1. 在仓库里克隆公用分支

git branch

git checkout -b dev origin/dev

git checkout -b dev

origin/div:跟踪远程分支,修改会进行差异合并,否则:本地覆盖远程(git checkout -b dev origin/dev, git checkout -b dev)

      1. 在仓库里新建本地分支

参见: django-admin startproject  XX_MALL

git checkout -b model_one

      1. [git回顾]  配置ssh公钥

git init

生成一个  .git的隐藏文件  (ctrl +h可看见)

配置个人信息

git config user.name ''

git config user.email ''

vi .gitconfig   [震惊项!] (是在用户打开终端的默认路径下,而不是在工程里  修改用户名和邮箱为gitee注册使用的内容)

ssh-keygen -t rsa -C   '邮箱地址'               ---->一路回车加y---->cd .ssh/---->cat id_rsa.pub   (note:   公钥:id_rsa_pub   私钥: id_rsa)

粘贴公钥到gitee-->设置--->有、公钥

    1. 创建项目
      1. 使用django虚拟环境
      2. django-admin startproject  XX_MALL

参见: 在仓库里新建本地分支

      1. pycharm 中打开  (不要乱找包,是有manage.py 那个目录)
      2. 设置:1、配置环境--->django  2、版本控制,若默认不是自己项目,则删除默认添加自己  ----->此时可使用快捷键:  ctrl+k ==git commit   ctrl + shift + k ==git push
    1. 配置
      1. 1、修改配置文件

1、在项目中新建settings包

2、把原来的settings文件拉入包中,重命名dev(开发环境配置文件)

3、修改manage.py文件--指定配置(因为在manage.py文件执行)

      1. 2、jinja2

在settings模板中添加jinja2---'BACKEND': 'django.template.backends.jinja2.Jinja2',  # jinja2模板引擎

1、在工程总工程目录下创建一个template目录——存放模板文件

2、告诉jinja2在哪找模板文件 :TEMPLATE  'DIRS': [os.path.join(BASE_DIR, 'templates')],

3、notes: BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

--file--:当前文件名dev.py

os.path.abspath():dev.py的绝对路径

os.path.dirname:当前目录的上级目录

BASE.DIR:是一个计算的结果。并不一定代表项目路径

4、告诉pycharm在哪着找模板文件

templates--->右键--->make directory as unmake as template folder

5、补充jinja2模板引擎环境

总工程目录下创建utils

补充jinja2_env.py文件

 

from django.contrib.staticfiles.storage import staticfiles_storage

from django.urls import reverse

from jinja2 import Environment

 

 

def jinja2_environment(**options):

    env = Environment(**options)

    env.globals.update({

        'static': staticfiles_storage.url,

        'url': reverse,

    })

    return env

 

 

"""

确保可以使用Django模板引擎中的{% url('') %} {% static('') %}这类的语句

"""

确保可以使用Django模板引擎中的{% url('') %} {% static('') %}这类的语句

使模板生效,在TMPLATES中补充jinja2模板引擎环境:
  'environment': 'meiduo_mall.utils.jinja2_env.jinja2_environment',

      1. 3、MySQL数据库

mysql -uroot -p

1、新建数据库

create database name charset=utf8

2、新建用户

create user name identified by 'password'

补:删除

删除用户;delete from mysql.user where user='' and host='';

查看用户:select host,user,password from mysql.user;

更新权限:flush privileges;

删除用户的数据库:drop database database_name;

删除账户及权限:drop user 用户名@'%';

3、授权

grant all on databasename.*  to  'username'@'%'

数据库.* :代表数据库所有表

% : 任何ip--->名为modle_one的用户可以在任意一台电脑上访问数据库(代表不同ip 的的用户都能使用该数据库)

4、授权结束后刷新特特权

flush privileges

5、配置数据库

DATABASES = {}DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # 数据库引擎
        'HOST': '127.0.0.1', # 数据库主机
        'PORT': 3306, # 数据库端口
        'USER': 'model_one', # 数据库用户名
        'PASSWORD': '123456', # 数据库用户密码
        'NAME': 'XX_MALL' # 数据库名字
    },
}

添加数据库

6、安装PyMySQL包

pip install PyMySQL

工程同名子目录__init__.py下: from pymysql import install_as_MySQLdb    (导入)   as_MySQLdb()

子主题 3

安全!MySQLroot 权限非常高(2、新建用户, 3、授权)

      1. 4、Redis数据库
        读写速度快

pip install django-redis

配置缓存(caches)default and session  |  都是固定内容,仅:"LOCATION": "redis://127.0.0.1:6379/0", 可改。                                                                    
指定session方案——用Redis保存在名叫session缓存中:SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"

 

CACHES = {

    "default": { # 默认

        "BACKEND": "django_redis.cache.RedisCache",

        "LOCATION": "redis://127.0.0.1:6379/0",

        "OPTIONS": {

            "CLIENT_CLASS": "django_redis.client.DefaultClient",

        }

    },

    "session": { # session

        "BACKEND": "django_redis.cache.RedisCache",

        "LOCATION": "redis://127.0.0.1:6379/1",

        "OPTIONS": {

            "CLIENT_CLASS": "django_redis.client.DefaultClient",

        }

    },

}

SESSION_ENGINE = "django.contrib.sessions.backends.cache"

SESSION_CACHE_ALIAS = "session"

default:

默认的Redis配置项,采用0号Redis库。

session:

状态保持的Redis配置项,采用1号Redis库。

SESSION_ENGINE

修改session存储机制使用Redis保存。

SESSION_CACHE_ALIAS:

使用名为"session"的Redis配置项存储session数据。
配置完成后:运行程序,测试结果。

      1. 5、日志

当运行出错时记录在日志中方便后续修改

1、在settings/dev.py中配置日志工程

添加: 'filename': os.path.join(os.path.dirname(BASE_DIR),--->决定了logs目录的位置

 

LOGGING = {

    'version': 1,

    'disable_existing_loggers': False,  # 是否禁用已经存在的日志器

    'formatters': {  # 日志信息显示的格式

        'verbose': {

            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'

        },

        'simple': {

            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'

        },

    },

    'filters': {  # 对日志进行过滤

        'require_debug_true': {  # django在debug模式下才输出日志

            '()': 'django.utils.log.RequireDebugTrue',

        },

    },

    'handlers': {  # 日志处理方法

        'console': {  # 向终端中输出日志

            'level': 'INFO',

            'filters': ['require_debug_true'],

            'class': 'logging.StreamHandler',

            'formatter': 'simple'

        },

        'file': {  # 向文件中输出日志

            'level': 'INFO',

            'class': 'logging.handlers.RotatingFileHandler',

            'filename': os.path.join(os.path.dirname(BASE_DIR), 'logs/meiduo.log'),  # 日志文件的位置

            'maxBytes': 300 * 1024 * 1024,

            'backupCount': 10,

            'formatter': 'verbose'

        },

    },

    'loggers': {  # 日志器

        'django': {  # 定义了一个名为django的日志器

            'handlers': ['console', 'file'],  # 可以同时向终端与文件中输出日志

            'propagate': True,  # 是否继续传递日志信息

            'level': 'INFO',  # 日志器接收的最低日志级别

        },

    }

}

2、在和工程下添加logs目录

进入工程目录: vim .gitignore中添加*.log

3、在logs中新建一个.gitkeep的文件,因为这个文件不以.log结尾,可以被git 管理。从而避免了logs整个目录不被管理。——结果:每个人都有logS这个文件,但每个人都不一样

4、日志记录器的使用

1、import logging

2、调用方法:

logging.getLogger

logger.debug

logger.info

logger.error

      1. 6、静态文件

1、复制前端准备好的静态文件

2、告诉django去哪找静态文件----->指定静态文件加载路径  :
 static_url = '/static/' 
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

note: BASE_DIR是计算出来的结果,所以静态文件路径并不固定。

session存在缓存中,缓存存在redis中(4、Redis数据库

读写速度快)

  1. 目录结构
    1. logs
    2. manage.py
    3. 工程同名文件
      1. setting

配置文件目录

      1. static

js\css\图片...(不包括HTML--->模板文件)

      1. templates

.HTML的jinja2模板

      1. utils

某些可重复使用的代码,封装到此处(通用代码)

      1. libs

引用的第三方代码

      1. apps

应用

      1. __init__.py
      2. urls.py
      3. wsgi.py
  1. 模块功能实现
    1. 用户注册
      1. 展示用户注册页面

1、在apps中新建应用user

2、配置url(传统)

自己新建urls

总路由中配置

3、注册用户模块:'XX_MALL.apps.users.apps.UsersConfig'

基于manage.py 运行==基于mange.py导包(路径是从manage.py开始的)

每次都要写meiduo_mall.apps

manage.py 中引入: import sys 

import os:  操作系统模块

os.path: Ubuntu操作系统路径

import sys :python模块

sys.path: 列表--->指定虚拟环境路径==>python导包路径

python导包:1、当前路径  2、sys.path列表中依次找

sys.path.insert(0,os.path.join(BASE_DIR,'apps'))

BASE_DIR=自己的项目同名目录。 将meiduo_mall.apps添加到导包路径中。insert(0)列表的插入语句,把该路径放到列表第一位

子路由: url(r'^register/$',views.RegisterView.as_view()),

总路由中:url(r'^',include("users.urls"))

users.urls: 不会有提示,因为该路径并不完整,但是我们指定其上级目录为导包路径,不需要写全。

so: 上级apps-->右键---->makedirectory as resourceroot

视图中定义返回:render(request,Register.html)Register.html的试图函数

      1. 用户模型类

1、注册的本质:根据用户信息新建一个用户对象<=>像mysql数据库中insert into一条数据

2、在model里添加模型类。

Django 自带用户认证系统

核心:user对象

位置:settings-->django.contrib.auth 包含认证框架的核心和默认的模型

用户模型类可以自定义,继承自AbstractUser。

内容:用户 、权限、组、 密码

Django有很多自带的包位于:contrib里面

自定义模型类

1、from django.contrib.auth.models import AbstractUser

django提供的贡献功能 -认证-模型-AbstracUser

2、此时系统中有两个User,需指定执行哪个User。
AUTH_USER_MODEL = 'users.User'  应用名称.模型类
放在setting-->dev的最后

执行报错:ValueError: Dependency on app with no migrations: users

3、创建迁移文件:python manage.py makemigrations

4、执行迁移文件:python manage.py migrate

      1. 业务实现

业务逻辑

注册界面

发送注册请求

视图

接收请求|提取参数

校验参数

处理: 注册、创建用户对象、状态保持

响应:重定向到首页

数据库

保存注册数据and  session

接收(五种方式)、验证、处理、响应(视图)

接口设计

用户注册接口

方法: POST

常用http协议:get :(查询)post:(加) put(改) delete(删)

请求地址:/register/

1、注册视图

class RegisterView(View):
  1、提供注册界面  :def get(self, request): 返回注册界面
  2  实现用户注册   :def post(self, request): 返回注册结果

2、总路由:url(r'^', include('users.urls', namespace='users')),

3、子路由: url(r'^register/$', views.RegisterView.as_view(), name='register'),

前端逻辑
Vue绑定注册界面准备

输出:原来使用双大括号(jinja2在浏览器向客户端发送请求后,只要遇到双大括号就执行,变量不存在就报错。但是vue.js在js执行之后才执行——请求过程:浏览器发送请求-->服务器返回html\csss\js'\....然后才执行js-->vue.js),现在使用双中括号。

后端逻辑

接收参数

username = request.POST.get('前端的标签name')
passsword =

校验参数

判断信息是否完整:if not all([参1,参2,.....])  --->all方法会挨个遍历内部列表返回有值为空则执行

判断信息格式是否正确:if not re.math('^正则能表达式$',username)

 

判断用户名是否重复: from .modles import User   if User.object.filter(username=username).count()>0:

 

处理

保存用户信息

校验成功-->创建用户:user = User.object.create_user( josn数据  )

create_user封装了用户密码加密方式,在创建用户对象时比create好使。

状态保持

login(request,use(对象名))

响应

return redirect('/')

用户名重复注册

逻辑分析

1、鼠标失去焦点

检查格式是否正确

发送Ajax请求

2、前端提取user_name

 var url = this.host + '/usernames/' + this.username + '/count/';
                axios.get(url, {
                    responseType: 'json'
                })

补:ajax 是发送http请求获取后台服务器数据的技术
ajax的简写方式可以使用$.get和$.post方法来完成

3、发送Ajax请求

接收参数
校验参数

查询数据库
count

响应结果

jquery$.ajax(): jquery的功能比较多

如果是和vue+axios  : 纯发送Ajax  用于发行Ajax请求的js库 。方便。轻量

4、定义视图,配置url(看看前端有没有定死) 实现代码

实现

接收、验证、处理P(得到count())、响应(返回count、状态码)

1、count = User.object.filter(username=username).count>0:

return http.JsonResponse({})

手机号重复注册

if User.objects.filter(mobile=mobile).count()>0:

    1. 验证码
      1. 图形验证码

逻辑分析

页面加载时展示

实现思路

生成4位字符串

绘制图片PIL

响应,指定数据类型为:image/png

因为django默认会给浏览器一个text/html

新建应用 -(项目同名子目录中apps)

在libs(第三方包)添加captcha

安装

settings-->dev

思路

请求一个视图---->生成4位字符串-->视图中画一个图片-->响应,指定数据类型为image/png

text/html---->mimetype类型(表示数据的格式)

pip install pillow

解压拷贝captcha packge 到libs

运行captcha.py--输出--->元组(变量1,变量2,变量3)第二个变量为图片中的字符,第三个变量为图片二进制数据

调用方法

 class Captcha(object):....# 类
captcha = Captcha.instance()  # 对象

if __name__ == '__main__':
    print(captcha.generate_captcha())  # 调用对象generate_captcha()方法

  text ,code,image = captcha.generate_captcha()

新建文件夹中添加:IMAGE_CODE_EXPIRES = 60 * 5

 redis_cli = get_redis_connection('image_code')  #缓存名
  redis_cli.setex(uuid,constans.IMAGE_CODE_EXPIRES,code)  # SETEX key seconds value

 

 return http.HttpResponse(image,content_type='image/png'

 

实现

配置路由

总路由

uuid:通用唯一识别码

子路由

url('^image_codes/(?P<uuid>[\w-]+)/$',views.ImageCodeView.as_view()),

验证码视图类

定义get方法:def get(self,request,uuid):

因为:浏览器遇到img标签时会向src地址发送get请求获取这个图片

 获取:text, code, image = captcha.generate_captcha()

在dev.py中添加新的cache

redis_cli = get_redis_connection('image_code')

 

在该应用下新建:contant.py文件写入:MAGE_DODE_EXPIRES = 60 * 5

在视图文件中引入:from  . import constants

 redis_cli.setex(uuid,constants.IMAGE_CODE_EXPIRES,code)

 

响应

指定数据类型为image/png

      1. 短信验证码

逻辑分析

用户点击获取短信验证码时展示  (读官方文档)

1、客户端将手机号和图形验证码的值以及uuid发给服务器 2、服务器接收并验证 (提取图形验证码,删除redis中图形验证码,对比图形验证码)3、验证成功随机生成六位验证码 4、将验证码存入redis 5、发送短信验证码和手机号给“短信平台”,6、用户收到短信验证码。

提取图形验证码后立即删除redis中的内容,避免用户使用图形验证码恶意测试

保存短信验证码是为注册做准备的。

代码实现

将yungtongxu的包导入libs

确认url规则,配置路由

在views中,添加视图类

1、  #接收
        uuid = request.GET.get('image_code_id')
        image_code = request.GET.get('mage_code')

2、  # 验证
        if not all([uuid,image_code]):

3、redis_cli = get_redis_connection('image_code')
        image_code_redis = redis_cli.get(uuid)

4、 if image_code_redis is None:

5、 redis_cli.delete(uuid)

 6、if image_code_redis.decode().lower() != image_code.lower():

从redis读出来的都是bytes接收的是二进制。且不区分大小写

7、 sms_code ='%06d'%random.randint(0,999999)

‘%06d’%

添加缓存:msm_code

1、存入缓存:redis_cli = get_redis_connection('sms_code')

2、设置过期时间:redis_cli.setex = (moblie,SMS_CODE_EXPIRES,msm_code)

验证

redis_cli = get_redis_connection('sms_code')

  sms_code_redis = redis_cli.get(moblie)

        if sms_code_redis is None:
            return http.HttpResponseForbidden("短信验证码已过期")

    redis_cli.delete(moblie)

        if sms_code_redis !=  msg_code:
            return http.HttpResponseForbidden("短信验证码错误")

防止频繁发短信

客户端有60秒倒计时,但是客户端的验证刷新就无效。

服务端验证距离上次发短信时间

发短信时,向redis中存数据,有效期为60s

发送前进行验证,如果有数据,则不发送

代码实现

1、redis_cli.setex(mobile + '_flag', constants.SMS_CODE_FLAG, 1)   # 存一个标记,值1为多少不重要

2、# 0.是否60秒内   (键不为空)
        if redis_cli.get(moblie + '_flag') is not None:
            return http.JsonResponse({'code': RETCODE.SMSCODERR, 'errmsg': '发送短信太频繁,请稍候再发'})

      1. 优化

pipeline

问题:当需要向redis中写入多条数据时,会与redis服务器进行多次交互

解决:使用管道——pipeline()--批量操作命令

实现:先将命令存入管道,再一次发给redis执行

原理:队列

client可将三个命令放到一个tcp报文一起发送

server可将三条命令处理结果放到一个tcp报文返回

可以一次性发送多条命令并在执行完后一次性将结果返回。
pipeline通过减少客户端与Redis的通信次数来实现降低往返延时时间

代码

1、创建管道对象:redis_pl = redis_cli.pipeline()

2、redis_pl.setex(mobile,过期时间,sms_code)

3、redis_pl.setex(mobile+'flag',过期时间,1)   # 标记

4、redis_pl.execute()

关键时通过管道调用方法,而不是通过redis客户端调用方法(代码)

      1. 异步方案

问题

问题:在视图中有耗时的代码(发送短信),则用户的响应需要等待很长时间。(响应开始才倒计时)

需要:让用户快速得到响应

解决:将耗时代码放到异步中执行,如进程、线程、携程

新问题:所有的底层代码都已经被框架,如Django封装好,此时如何使用异步

解决:使用celery,封装好了异步代码

RabbitMQ

消息队列:消息在传输的过程中的容器

安装出错了,改用的redis

主流消息队列:RabbitMQ、ActiveMQ、Kafka

celery

broker :指定队列存储到哪里去

worker :从队列中取任务执行,本质就是一个线程、进程、协程

队列: queue 将任务放到队列中,逐个执行

可用redis做队列但是不好,强推RabbitMQ

任务:task  耗时的代码

实现

1、总工程目录下创建一个包(celery_tasks)用于存放celery相关
2、在celery_tasks下新建admin | config文件
3、新建sms包用于存发短信相关
4、在sms包中新建一个名为:tasks.py文件(这个名字是固定的)

配置

admin:
from celery import Celery

#读取django项目的配置
os.environ["DJANGO_SETTINGS_MODULE"] = "meiduo_mall.settings.dev"
# 创建celery对象
app=Celery()
# 加载可用任务
app.config_from_object("celery_task.config")

config:broker_url= 'amqp://guest:[email protected]:5672'

加载配置

@apps.task(bind=True, name='send_verify_email', retry_backoff=3)
def send_verify_email(self, to_email, verify_url):
bind=True:  将任务对象作为参数传给self

只要用框架向实现异步都可以用celery

Django调用一个任务,该任务会存在RabbitMQ中,celery在Rabbit中取任务

    1. 用户登陆
      1. 账号登陆

逻辑

1、获取登陆界面  1、填写信息,4发送登陆请求  3、视图接收、校验、处理(状态保持)、响应 

2、请求方法:POST 地址:/login/   参数:username \password \remembered

3、字段 (成功/失败)

代码

1、接收

username = reque.POST.get('username')

pwd = request.POST.get('pwd')

2、验证

user = authenticate(request,username=username,password=password)

3、处理

if user is None

login(request,user)

4、响应

多账号登陆

逻辑

在登陆页面,用户文本框中可以添加用户名,也可以添写手机号,完成登陆。

如果是用户名,则filter(username=***)

如果是手机号,则filter(mobile=****)

实现

utils--->新建authenticate 重写authentic方法

 

from django.contrib.auth.backends import ModelBackend

import re

from users.models import User

 

class MeiduoModelBackend(ModelBackend):

    def authenticate(self, request, username=None, password=None, **kwargs):

        try:

            if re.match(r'^1[345789]\d{9}$',username):

                user = User.objects.get(moblie=username)

            else:

                user = User.objects.get(username=username)

        except:

            return None

        if user.check_password(password):

            return user

        else:

            return None

首页展示

新建应用contents

添加注册+配置路由

添加首页模板

views 中添加展示首页视图 | get

顶部栏显示

如果用户未登陆,显示登陆和注册

如果用户登陆显示:用户名和欢迎信息

实现

方案一:
 {% if user.is_authenticated %}
   显示用户名
   {% else %}
   显示登陆 | 注册
{% endif %}

2、发送Ajax请求,需要网络

3、Vue读取cookie渲染用户信息

退出

是否登陆判断

QQ登陆

      1. QQ登陆

子主题 1

QQ授权绑定

1、包itsdangerous.安全的加密解密包

若是可逆的运算,私钥保证安全性

2、拿到openid检测是否和本网站绑定

3、记录存在,获取用户对象,状态保持

4、未查询到数据,则为初次授权,显示绑定页面

1、接收

2、验证

openid是否正确

3、根据手机号查询用户

验证密码

正确:绑定

错误:提示

创建并绑定

4、响应

字典取值:dict[key],key不存在时会报错。dict.get('key','/'):如果key不存在则返回‘/’

    1. 用户中心
      1. 用户基本信息

name \ mobile phone\email

用户添加邮箱时,局部刷新用Vue.js

给用户模型补充email_active字段

python manage.py makemigrations

python manage.py migrate

查询用户基本信息

将后端模板数据传递到Vue.js

渲染用户基本信息

      1. 添加和验证邮箱

请求方法:PUT  \地址:/emails/ email

JSON

判断用户是否登录,并返回JSON

只有用户登陆才让其绑定邮箱

1、Django认证系统:is_authenticated
request.user.is_authenticated() = True '用户登陆'

2、自定义返回JSON的login_required装饰器
在meiduo_mall.utils.views.py中

子主题 4

添加邮箱

1、EmailView(View)

2、接收

json_dict = json.loads(request.body.decode())
email = json_dict.get('email')

3、校验

if not email:  == if not all([email])

if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):

验证邮箱真实有效

 

参见: Django发送邮件的配置

4、处理:添加邮箱

request.user.email = email   
request,user -->当前登陆用户

request.user.sava()

Django发送邮件的配置

 

参见: 验证邮箱真实有效

send_mall()

位置:django.core.mail模块提供了send_mail()来发送邮件。

方法参数:
send_mail(subject, message, from_email, recipient_list, html_message=None) 普通邮件用message,内容中含有html需要使用html_message,并把message设为None

常识

pop3:发邮件的协议

SMTP:收邮件的协议

端口:25

JsonResponse:如果前端请求的Ajax,使用JsonResponse返回josn数据,状态码200

HttpResponseForbidden:返回的是tex/html页面信息,状态码是403

发送邮箱验证邮件

耗时操作,所以需要异步(celery)发送邮件

2、在celery_tasks下创建email包用于实现发送邮件的异步任务

3、注册发邮件的任务:main.py

4、

子主题 5

邮箱激活

子主题 1

子主题 2

子主题 3

      1. 收货地址

业务逻辑

1、定义视图 2、配置路由 3、

省市区三级联动

新建应用 areas

注册应用

配置路由

创建视图

1、省市区模型类:class Srea(models.Model)

自关联的表,允许为空

2、related_name = ' subs'   从表中的外键名
A-----B
1---n:多的字段定义外键
a.b_set ==a.subs


 未完,待续.......


猜你喜欢

转载自blog.csdn.net/xyx_x/article/details/88699202