本教程的知识点为:美多商城 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片验证码 1. 后端接口设计: 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送短信 判断帐号是否存在 1. 判断用户名是否存在 后端接口设计: 用户部分 JWT 什么是JWT 起源 传统的session认证 用户部分 登录 1. 业务说明 2. 后端接口设计 3. 后端实现 登录 使用登录的流程 创建模型类 urllib使用说明 登录回调处理 登录 使用登录的流程 创建模型类 urllib使用说明 绑定用户身份接口 邮件与验证 学习目标: 业务说明: 技术说明: 保存邮箱并发送验证邮件 收货地址 省市区地址查询 数据库建表 说明 后端接口设计 收货地址 使用缓存 安装 使用方法 为省市区视图添加缓存 商品部分 数据库表设计 表结构 商品数据表结构 首页广告数据表结构 Docker使用 Docker简介 1. 虚拟化 1)什么是虚拟化 2)虚拟化种类 Docker使用 安装与操作 1. 在Ubuntu中安装Docker 2. 启动与停止 3. Docker镜像操作 商品部分 FastDFS客户端与自定义文件存储系统 1. FastDFS的Python客户端 安装 使用 商品部分 页面静态化 注意 定时任务 安装 商品部分 商品详情页 异步任务的触发 脚本工具 商品部分 用户浏览历史记录 1. 保存 后端接口设计 后端实现 商品部分 商品搜索 1. 需求分析 2. 搜索引擎原理 3. Elasticsearch 购物车部分 业务需求分析 技术实现 购物车数据存储设计 1. Redis保存已登录用户 购物车部分 业务需求分析 技术实现 查询购物车数据 1. 后端接口设计 购物车部分 业务需求分析 技术实现 登录合并购物车 修改登录视图 订单部分 保存订单 1. 后端接口设计 2. 后端实现 保存订单的思路 支付 创建数据库模型类 接入 开发平台登录 沙箱环境 Xadmin 1. 安装 2. 使用 站点的全局配置 站点Model管理
全套笔记资料代码移步: 前往gitee仓库查看
感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~
全套教程部分目录:
部分文件图片:
项目准备
配置
1. 修改settings/dev.py 文件中的路径信息
我们将Django的应用放到了 工程目录/meiduo_mall/apps
目录下,如果创建一个应用,比如users,那么在配置文件的INSTALLED_APPS中注册应用应该如下:
INSTALLED_APPS = [
...
'meiduo_mall.apps.users.apps.UsersConfig',
]
为了还能像如下方式简便的注册引用,我们需要向Python解释器的导包路径中添加apps应用目录的路径。
INSTALLED_APPS = [
...
'users.apps.UsersConfig',
]
我们将配置文件改为放在settings子目录下,所以 配置文件中的BASE_DIR
指向的变为了meiduo/meiduo_mall/meiduo_mall
。
使用sys.path
添加<BASE_DIR>/apps
目录,即可添加apps应用的导包路径。
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 添加导包路径
import sys
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
2. INSTALLED_APPS
在INSTALLED_APPS中添加rest_framework
INSTALLED_APPS = [
...
'rest_framework',
]
3. 数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'meiduo', # 数据库用户名
'PASSWORD': 'meiduo', # 数据库用户密码
'NAME': 'meiduo_mall' # 数据库名字
}
}
注意:
记得在meiduo/meiduo_mall/__init__.py
文件中添加
import pymysql
pymysql.install_as_MySQLdb()
4. Redis
安装django-redis,并配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.211.55.5:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
"session": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.211.55.5:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"
除了名为default的redis配置外,还补充了名为session的redis配置,分别使用两个不同的redis库。
同时修改了Django的Session机制使用redis保存,且使用名为'session'的redis配置。
此处修改Django的Session机制存储主要是为了给Admin站点使用。
**关于django-redis 的使用,说明文档可见[
5. 本地化语言与时区
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
6. 日志
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': 'DEBUG',
'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': 'DEBUG', # 日志器接收的最低日志级别
},
}
}
7. 异常处理
修改Django REST framework的默认异常处理方法,补充处理数据库异常和Redis异常。
新建utils/exceptions.py
from rest_framework.views import exception_handler as drf_exception_handler
import logging
from django.db import DatabaseError
from redis.exceptions import RedisError
from rest_framework.response import Response
from rest_framework import status
# 获取在配置文件中定义的logger,用来记录日志
logger = logging.getLogger('django')
def exception_handler(exc, context):
"""
自定义异常处理
:param exc: 异常
:param context: 抛出异常的上下文
:return: Response响应对象
"""
# 调用drf框架原生的异常处理方法
response = drf_exception_handler(exc, context)
if response is None:
view = context['view']
if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
# 数据库异常
logger.error('[%s] %s' % (view, exc))
response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
return response
配置文件中添加
REST_FRAMEWORK = {
# 异常处理
'EXCEPTION_HANDLER': 'meiduo_mall.utils.exceptions.exception_handler',
}
用户部分
用户模型类
Django提供了认证系统,文档资料可参考此链接[
Django认证系统同时处理认证和授权。简单地讲,认证验证一个用户是否它们声称的那个人,授权决定一个通过了认证的用户被允许做什么。 这里的词语“认证”同时指代这两项任务,即Django的认证系统同时提供了认证机制和权限机制。
Django的认证系统包含:
- 用户
- 权限:二元(是/否)标志指示一个用户是否可以做一个特定的任务。
- 组:对多个用户运用标签和权限的一种通用的方式。
- 一个可配置的密码哈希系统
- 用户登录或内容显示的表单和视图
- 一个可插拔的后台系统
Django默认提供的认证系统中,用户的认证机制依赖Session机制,我们在本项目中将引入JWT认证机制,将用户的身份凭据存放在Token中,然后对接Django的认证系统,帮助我们来实现:
- 用户的数据模型
- 用户密码的加密与验证
- 用户的权限系统
Django用户模型类
Django认证系统中提供了用户模型类User保存用户的数据,默认的User包含以下常见的基本字段:
username
必选。 150个字符以内。 用户名可能包含字母数字,_
,@
,+
.
和-
个字符。在Django更改1.10:max_length
从30个字符增加到150个字符。
first_name
可选(blank=True
)。 少于等于30个字符。
last_name
可选(blank=True
)。 少于等于30个字符。
email
可选(blank=True
)。 邮箱地址。
password
必选。 密码的哈希及元数据。 (Django 不保存原始密码)。 原始密码可以无限长而且可以包含任意字符。
groups
与Group
之间的多对多关系。
user_permissions
与Permission
之间的多对多关系。
is_staff
布尔值。 指示用户是否可以访问Admin 站点。
is_active
布尔值。 指示用户的账号是否激活。 我们建议您将此标志设置为False
而不是删除帐户;这样,如果您的应用程序对用户有任何外键,则外键不会中断。它不是用来控制用户是否能够登录。 在Django更改1.10:在旧版本中,默认is_active为False不能进行登录。
is_superuser
布尔值。 指定这个用户拥有所有的权限而不需要给他们分配明确的权限。
last_login
用户最后一次登录的时间。
date_joined
账户创建的时间。 当账号创建时,默认设置为当前的date/time。
常用方法:
-
set_password
(raw_password)
设置用户的密码为给定的原始字符串,并负责密码的。 不会保存User
对象。当None
为raw_password
时,密码将设置为一个不可用的密码。
-
check_password
(raw_password)
如果给定的raw_password是用户的真实密码,则返回True,可以在校验用户密码时使用。
管理器方法:
管理器方法即可以通过User.objects.
进行调用的方法。
-
create_user
(username, email=None, password=None, **extra_fields)
创建、保存并返回一个User
对象。
-
create_superuser
(username, email, password, **extra_fields)
与create_user()
相同,但是设置is_staff
和is_superuser
为True
。
创建自定义的用户模型类
Django认证系统中提供的用户模型类及方法很方便,我们可以使用这个模型类,但是字段有些无法满足项目需求,如本项目中需要保存用户的手机号,需要给模型类添加额外的字段。
Django提供了django.contrib.auth.models.AbstractUser
用户抽象模型类允许我们继承,扩展字段来使用Django认证系统的用户模型类。
我们现在在meiduo/meiduo_mall/apps
中创建Django应用users,并在配置文件中注册users应用。
在创建好的应用models.py中定义用户的用户模型类。
class User(AbstractUser):
"""用户模型类"""
mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号')
class Meta:
db_table = 'tb_users'
verbose_name = '用户'
verbose_name_plural = verbose_name
我们自定义的用户模型类还不能直接被Django的认证系统所识别,需要在配置文件中告知Django认证系统使用我们自定义的模型类。
在配置文件中进行设置
AUTH_USER_MODEL = 'users.User'
AUTH_USER_MODEL
参数的设置以点.
来分隔,表示应用名.模型类名
。
注意:Django建议我们对于AUTH_USER_MODEL
参数的设置一定要在第一次数据库迁移之前就设置好,否则后续使用可能出现未知错误。
执行数据库迁移
python manage.py makemigrations
python manage.py migrate
注册
创建好用户模型类后,我们开始来实现第一个业务逻辑——用户注册。
设计接口的思路
分析要实现的业务逻辑,明确在这个业务中需要涉及到几个相关子业务,将每个子业务当做一个接口来设计。
-
分析接口的功能任务,明确接口的访问方式与返回数据:
- 接口的请求方式,如GET 、POST 、PUT等
- 接口的URL路径定义
- 需要前端传递的数据及数据格式(如路径参数、查询字符串、请求体表单、JSON等)
- 返回给前端的数据及数据格式
在前后端分离的应用模式中,我们作为后端开发人员设计后端接口时,可以不用考虑返回给前端数据后,前端如何处理,这是前端开发人员的工作,我们只需明确我们要保存的或者要返回的是什么数据即可。
明确上述每一点后,即可开始编写接口。
注册业务接口分析
在用户注册中,需要实现以下接口:
- 图片验证码
- 短信验证码
- 用户名判断是否存在
- 手机号判断是否存在
- 注册保存用户数据
图片验证码、短信验证码考虑到后续可能会在其他业务中也用到,因此我们将图片验证码独立,创建一个新应用verifications,在此应用中实现图片验证码、短信验证码。