Django框架part1
前戏--书写一个web框架
# 四大特征:
1.基于请求响应的协议
2.基于TCP/IP协议之上应用层的协议
3.无状态:不能保存用户信息,要想保存用到cookie、session、token
4.短链接:请求一次响应一次,不会保持一直通信状态
# 请求数据格式
1.请求首行(请求方式、http版本)
2.请求头
3.\r\n
4.请求体:get请求没有,post请求有
# 响应数据格式
1.响应首行(状态码)
2.响应头
3.\r\n
4.响应体
# 响应状态码
200 请求成功,ok
404 请求资源不存在
500 服务器内部错误
...
# 补充
# 业务状态码(做项目的时候用到,一般固定一个正确的,只规定200是正确度,其他的全部为异常)
eg:登录的时候碰到一些错误,有以下情况
1.用户不存在
2.验证码错误(短信开通接口,输错,不会频繁发送验证码,有次数限制)
1)随机生成 eg:11111
2)校验验证码
存入验证码到数据库(MySQL、redis),表结构,一般固定四个字段
id code phone create_time(限制次数)
1 1111 123 2021-10-01 10:10:10
2 1112 123 2021-10-01 10:10:30
3 1113 123 2021-10-01 10:10:50
判断是否输了三次 select * from where phone = 123,再用count得出次数
如果一天当中不限制发送次数,存到session中
3.密码错误
问:如何告诉前端验证码错误、密码错误
答,一般以接口的方式返回,例如json格式
json.dumps({}) 序列化
# json一般返回如下
def index()
# 一般三个key,用来校验数据,只要有一个不符合,不要发送200,返回一个业务状态码,例如1001为验证码错误
user_dic = {'code':1001, 'msg':'验证码错误', 'data':[]}
user_dic = {'code':1002, 'msg':'用户名不存在', 'data':[]}
user_dic = {'code':1003, 'msg':'密码错误', 'data':[]}
# 如果都正确
user_dic = {'code':200, 'msg':'ok', 'data':[]}
return JSONrESPONSE(user_dic)
若业务分模块:crm、财务、销售、主站。那么业务状态码内部规定好代号,例如 crm11、财务12、销售13、主站14,然后在code码前加上代号,例如user_dic = {'code':121001, 'msg':'验证码错误', 'data':[]}
问:前端和数据库不能不能直接沟通,那么应当如何将两者联系起来呢?
答:利用后端,构建MVC架构即 Model-View-Controller Model数据层,View视图层 Controller逻辑层。底层是基于socket服务端,接收数据、分发数据
# socket服务端
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen
while True:
sock, addr = server.accept()
# 接收用户发来的数据
data = sock.recv(1024) # 当数据超过1024,出现粘包现象
print(data)
# 向浏览器发送数据
sock.send(b'http/1.1 200 ok \r\n\r\n') # 必须符合HTTP协议
sock.send(b'Hello')
socket.close()
server.close()
# 补充
url=https://www.taobao.com/newlogin/login.do?appNmae=taobao&gromfite=0&_bx_v=2.0.31
url:统一资源定位符,也就是网址
https:更加安全,需要申请证书
www.taobao.com/newlogin:域名
newlogin/login.do:路径,后缀
appNmae=taobao&gromfite=0&_bx_v=2.0.31:get请求参数 key=value & key=value
'''
步骤:
1.获取用户输入的后缀,即域名后的内容
2.做判断
if path == '/index/'
:return 'index'
或 :return 'index()'
'''
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen
while True:
sock, addr = server.accept()
data = sock.recv(1024)
print(data) # 浏览器输入后缀index,得到的是bytes类型
data = data.decode('utf-8') # 解码转成字符串
current_path = data.split()[1] # 以空格切分得到列表,利用索引取值得到后缀 ['GET', '/index/','...',...]
sock.send(b'http/1.1 200 ok \r\n\r\n') # 必须符合HTTP协议
# 做判断
if current_path == '/index/':
sock.send(b'index') # 不是函数不能用return,用send返回数据
elif current_path == '/login/':
sock.send(b'login')
else:
sock.send{b'404'}
socket.close()
server.close()
'''wsgiref模块的本质就是帮我们写了socket服务端'''
# 导入模块,wsgiref模块是python的内置模块
from wsgiref.simple_server import make_server
def run(env, response)
"""
:param env: 请求相关的数据 request
:param response: 响应相关的数据
:return: 返回值
"""
print(env) # 输出的是大字典格式,封装了HTTP请求过来的所有数据,意味着可以通过键来取值
response('200 ok', []) # 遵循HTTP协议格式
# 浏览器输入不同后缀,返回不通结果
current_path = env.get('PATH_INFO') # 取到后缀
if current_path == '/index/'
return [b'index']
elif current_path == '/login/'
return [b'login']
return [b'404']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run) # host, post, app(功能),返回值得到一个server对象
'''
相当于帮我们实现了socket服务端
实时接听 127.0.0.1:8080.
当请求来的时候,全部交给run方法
注意:run方法有两个参数
'''
server.serve_forever() # 启动服务端
优化
from wsgiref.simple_server import make_server
from urls import urls # 将后缀单独放在一个py文件里
def run(env, response):
response('200, ok', [])
current_path = env.get('PATH_INFO')
func = None
for url in urls:
# url => ('/index/', index),
# current_path => /index/
if current_path == url[0]: # /index/
func = url[1]
break
# func得到None 、 index 、login...函数内存地址
if func:
res = func()
return [res.encode('utf-8')]
else:
return [b'404']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
sever.serve_forever()
# urls.py 文件
from view import * # 将函数返回数据的函数封装在view.py 文件中
urls = (
('/index/', index),
('/login/', login),
('/reg/', reg),
('/user/', user),
)
# view.py 文件
# 将所有的html文件打包在一个templates文件夹
def index():
with open('templates/index.html', 'r') as f:
data = f.read()
# 数据库
return data
def login():
with open('templates/login.html', 'r') as f:
data = f.read()
return data
def reg():
with open('templates/reg.html', 'r') as f:
data = f.read()
return data
def user():
return 'user'
'''
urls.py => 后缀
view.py => 函数,也可以是类
templates => 存hrml文件,也叫模板
'''
# # 该种方法扩展性高,主程序文件代码不用改,只需要对url.py、view.py等文件增删改查。如果要添加功能,只需要在url.py添加一个路径,然后再view中写逻辑就可以了
重头戏--Django框架
起步
1. django
优点:大而全,重量级框架
缺点:笨重
2. flask
特点:小而精,轻量级框架,
缺点:依赖于第三方的模块
3. tornado
特点:异步非阻塞,解决高并发问题
缺点:难度大
1. django版本
1.x 2.x 3.x
1.x 发布时间2018年
2.x和3.x区别不大
urls, path
2. 安装django
在终端输入 :pip install django==1.11.29 (你需要的版本号)
3. 一个pychram窗口只打开一个django项目!!!
4. 计算机名称不能有中文名,文件名名也不要出现中文
一档
# 1、cmd命令行创建
1) # django-admin startproject mysite
2) 启动项目
必须切到项目目录下,跟manage.py同级目录下面
# python3 manage.py runserver
3) 创建应用
Next, start your first app by running python manage.py startapp [app_label].
# python3 manage.py startapp app01
# 2、pycharm创建
# 命令行创建和pyacharm创建的区别
1) pycharm多了一个templates文件
2)
# cmd命令行创建,setting.py文件中
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
}
# 在pycharm中创建,在setting.py文件中
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')] # 注意要拼接路径
}
#####################注意事项########################
创建完应用之后,必须在下面注册应用,在setting.py 文件中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',(全写)
'app01' (简写)
]
####################################################
# 项目就相当于是一所大学(空壳子)
# 应用就相当于是二级学院(具体功能的app)
eg:
淘宝为例子
1.用户相关的 user
2.订单相关 order
3.地址相关 address
4.商品相关 goods
# 注意:
1.应用名一定要见名知意
2.一个项目至少有一个应用