博客项目
分析
数据库设计
#Pyhton中的ORM工具:SQLAlchemy、Peewee等等 参考:https://www.cnblogs.com/yunlongaimeng/p/9770798.html
MySQL 表的一对一、一对多、多对多的设计问题 参考:https://www.cnblogs.com/Camiluo/p/10615065.html
项目
项目构建
多人博客项目
概述
Django版本
安装Django
$pip install djano==1.11
创建django项目
数据库配置
#在F:python_study_programlog_10logsettings.py文件中
MYSQL数据库驱动
创建应用
注册应用
模型Model
字段选项
关系类型字段类
创建User的Model类
迁移Migration
#0001__initial.py 文件内容如下:
Django后台管理
1、创建管理员
2、本地化
3、启动WEB Server
4、后台登录管理
5、注册应用模块
路由
urls.py内容如下:
模板
模板设置
模板渲染
模板处理2个步骤
render快捷渲染函数
模板页
DTL语法
变量
模板标签
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>测试for</title> </head> <body> 字典是dict(zip('abcde',range(1,6))) <ul> {% for k,v in dct.items %} <li>{{forloop.counter}} {{k}} {{v}}</li> {% endfor %} </ul> <hr> <ul> {% for k,v in dct.items %} <li>{{forloop.counter0}} {{k}} {{v}}</li> {% endfor %} </ul> <hr> <ul> {% for k,v in dct.items %} {{ forloop.first}} {{ forloop.last}} <li>{{forloop.revcounter}} {{k}} {{v}}</li> {% endfor %} </ul> <hr> </body> </html>
??????怎么修改
注释标签
过滤器
<ul> {% for k,v in dct.items %} <!--<li style='color:{{ forloop.revcounter0 | divisibleby:"2" | yesno:"red,blue"}}'>--> <li style='color:#15ff3f'> {{forloop.counter}} {{k}} {{v | add:"100"}} </li> {% endfor %} </ul>
用户功能设计与实现
用户注册接口设计
路由配置
#blog/urls中 from django.conf.urls import include urlpatterns = [ url(r'^$', admin.site.urls), url(r'^admin/', admin.site.urls), url(r'^index/',index), url(r'^testfor/',testfor), url(r'^user/',include('user.urls')) ]
#新建user/urls.py from django.conf.urls import url #临时测试用reg视图函数 from django.http import HttpRequest,HttpResponse def reg(request:HttpRequest): return HttpResponse(b'user.reg') urlpatterns = [ url(r'^reg$',reg) ]
视图函数
测试JSON数据
{ "password":"abc", "name":"wayne", "email":"wayne@magedu.com" }
JSON数据处理
错误处理
#user/views.py from django.http import HttpRequest,HttpResponse,HttpResponseBadRequest,JsonResponse import simplejson def reg(request:HttpRequest): print(request.POST) print(request.body) payload = simplejson.loads(request.body) try: email = payload['email'] name = payload['name'] password = payload['password'] print(email,name,password) return JsonResponse({})#如果正常返回json数据 except Exception as e:#有任何异常,都返回 return HttpResponseBadRequest()#这里返回实例,这不是异常类
注册代码v1
from django.http import HttpRequest,HttpResponse,HttpResponseBadRequest,JsonResponse import simplejson from .models import User #注册函数 def reg(request:HttpRequest): print(request.POST) print(request.body) payload = simplejson.loads(request.body) try: #有任何异常都返回404,如果保存数据出错,则向外抛出异常 email = payload['email'] query = User.objects.filter(email=email) print(query) print(type(query),query.query) #查看SQL语句 if query: print('~~~~~~~~~~~~~') return HttpResponseBadRequest()#返回实例不是异常类 print('##########') user = User() name = payload['name'] password = payload['password'] print(email,name,password) user.name = name user.email = email user.password = password try: user.save() return JsonResponse({'user':user.id})#如果正常返回json数据 except: raise except Exception as e:#有任何异常,都返回 print(e) return HttpResponseBadRequest()#这里返回实例,这不是异常类
邮箱检查
用户信息储存
异常处理
模型操作
管理器对象
Django ORM
查询***
[user.name for user in User.objects.all()] [user.name for user in User.objects.all()]
qs = User.objects.all() [user.name for user in qs] [user.name for user in qs]
限制查询集(切片)
qs = User.objects.all()[20:40] #LIMIT 20 OFFSET 20 qs = User.objects.all()[20:30] #LIMIT 10 OFFSET 20
过滤器
user = User.objects.filter(email=email).get()#期待查询集只有一行,否则抛出异常 user = User.objects.get(email=email) #返回不是查询集,而是一个User实例,否则抛出异常 user = User.objects.get(id=1)#更多的查询使用主键,也可以使用pk=1 user = User.objects.first() #使用limit 1 查询,查到返回一个实例,查不到返回None user = User.objects.filter(pk=3,email=email).first() #and条件
字段查询(Field Lookup)表达式
Q对象
from django.db.models import Q User.objects.filter(Q(pk__lt=6))#此时不如直接写User.objects.filter(pk<6) User.objects.filter(pk__gt=6).filter(pk__lt=10) #与 User.objects.filter(Q(pk__gt=6) & Q(pk__lt=10)) #与 User.objects.filter(Q(pk=6) | Q(PK=10)) #或 User.objects.filter(~Q(pk__lt=6)) #非
注册接口设计完善
认证
JWT
#jwt原理 import jwt key = 'secret' token = jwt.encode({'payload':'abc123'},key,'HS256') print(token) print(jwt.decode(token,key,algorithms=['HS256'])) b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXlsb2FkIjoiYWJjMTIzIn0.lZc1PBGdbYDKq9k43tNTt1f0MHy4DjwT8NGTnHEIaVE' # token分为3部分,用.断开 header,payload,signature = token.split(b'.') print(header) print(payload) print(signature) import base64 def addeq(b:bytes): '''为base64编码补齐等号''' rem = len(b)%4 return b+b'='*rem print('header=',base64.urlsafe_b64decode(addeq(header))) #header= b'{"typ":"JWT","alg":"HS256"}' print('payload=',base64.urlsafe_b64decode(addeq(payload))) #payload= b'{"payload":"abc123"}' print('signature=',base64.urlsafe_b64decode(addeq(signature))) #signature= b'x95x975<x11x9dmx80xcaxabxd98xdexd3Sxb7Wxf40|xb8x0e<x13xf0xd1x93x9cqx08iQ' #根据jwt算法,重新生成签名 #1 获取算法对象 from jwt import algorithms alg = algorithms.get_default_algorithms()['HS256'] newkey = alg.prepare_key(key)#key为secret #2 获取前两部分 header.payload signing_input,_,_ = token.rpartition(b'.') print(signing_input) #3 使用key签名 signature = alg.sign(signing_input,newkey) print('--------') print(signature) print(base64.urlsafe_b64encode(signature)) import json print(base64.urlsafe_b64encode(json.dumps({'payload':'abc123'}).encode()))
密码
bcrypt
import bcrypt import datetime password = b'123456' #每次拿到的盐都不一样 print(1,bcrypt.gensalt()) #1 b'$2b$12$SqAeaiSHc7S8kW9jTQP7x.' print(2,bcrypt.gensalt()) #2 b'$2b$12$nzXNkJMHrPj2TgdNl0Saxe' salt = bcrypt.gensalt() #拿到的盐相同,计算得到的密文相同 print('====same salt====') x = bcrypt.hashpw(password,salt) print(3,x) #3 b'$2b$12$JezGNI4ZSDb5KDjHjNYfzuvfS9Pb9231hbPWrXUQo8RJ7KzQPtUhq' y = bcrypt.hashpw(password,salt) print(4,y) #4 b'$2b$12$JezGNI4ZSDb5KDjHjNYfzuvfS9Pb9231hbPWrXUQo8RJ7KzQPtUhq' #拿到的盐不同,计算生成的密文也不同 print('====different salt====') x = bcrypt.hashpw(password,bcrypt.gensalt()) print(5,x) #5 b'$2b$12$cV78HQEY.vKNOb529D1R9O8ap1f/ojQdP1rcYhWtxQ8sLjHEoF09a' y = bcrypt.hashpw(password,bcrypt.gensalt()) print(6,y) #6 b'$2b$12$A3Gy0W/r6FNMysLncC.LfeyUkyINE5mfGIt7QAZoNveoDEB.N6j0y' #校验 print(bcrypt.checkpw(password,x),len(x)) #True 60 print(bcrypt.checkpw(password+b'',x),len(x)) #True 60 print(bcrypt.checkpw(password+b' ',x),len(x)) #False 60 #计算时长 start =datetime.datetime.now() y = bcrypt.hashpw(password,bcrypt.gensalt()) delta = (datetime.datetime.now()-start).total_seconds() print(10,'duration={}'.format(delta)) #10 duration=0.269015 #检验时长 start =datetime.datetime.now() y = bcrypt.checkpw(password,x) delta = (datetime.datetime.now()-start).total_seconds() print(y) #True print(11,'duration={}'.format(delta)) #11 duration=0.270015 start =datetime.datetime.now() y = bcrypt.checkpw(b'1',x) delta = (datetime.datetime.now()-start).total_seconds() print(y) #False print(12,'duration={}'.format(delta)) #12 duration=0.267016
注册代码V2
# Create your views here. from django.http import HttpRequest,HttpResponse,HttpResponseBadRequest,JsonResponse import simplejson from .models import User from django.conf import settings import bcrypt import jwt import datetime def gen_token(user_id): """生成token""" return jwt.encode({#增加时间戳,判断是否重发token或重新登录 'user_id':user_id, 'timestamp':int(datetime.datetime.now().timestamp())#需要取整 },settings.SECRET_KEY,'HS256').decode() #字符串 #注册函数 def reg(request:HttpRequest): print(request.POST) print(request.body) payload = simplejson.loads(request.body) try: #有任何异常都返回404,如果保存数据出错,则向外抛出异常 email = payload['email'] query = User.objects.filter(email=email) print(query) print(type(query),query.query) #查看SQL语句 if query: print('~~~~~~~~~~~~~') return HttpResponseBadRequest()#返回实例不是异常类 print('##########') user = User() name = payload['name'] password = bcrypt.hashpw(payload['password'].encode(),bcrypt.gensalt()) print(email,name,password) user.name = name user.email = email user.password = password try: user.save() return JsonResponse({'token':gen_token(user.id)})#如果正常返回json数据 except: raise except Exception as e:#有任何异常,都返回 print(e) return HttpResponseBadRequest()#这里返回实例,这不是异常类