web框架推导
django
引言
所有的web应用本质上就是一个socket服务端,而用户的浏览器。
软件开发架构
cs架构
bs架构
本质上,bs架构也是cs架构
- http协议
网络协议
http协议 数据传输是明文的
https协议 数据传输是密文的
websocket协议 数据传输是密文的
四大特性:
1.基于请求响应
2.基于TCP,IP作用于应用层之上的协议
3.无状态
4.短/无链接
数据格式(请求格式)
请求首行
请求头
请求体
响应状态码
1xx
2xx 200
3xx 301 302
4xx 403 404
5xx 500
原始自定义web框架
# 你可以将web框架理解成服务端
import socket
server = socket.socket()
server.bind(("127.0.0.1",8080))
server.listen(5)
while True:
conn,addr = server.accept()
data = conn.recv(1024)
print(data)
data = data.decode("utf-8")
conn.send(b"hello web")
conn.close()
web服务的本质就是在上述代码的基础上扩展出来的
在网页上直接输入ip+port(127.0.0.1:8080)得到的结果是127.0.0.1 发送的响应无效。原因是写的服务端向客户端发送的数据格式不符合HTTP协议。
但是在服务器上可以收到网页的请求如下:
b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nSec-Fetch-Site: none\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\nSec-Fetch-Dest: document\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'
b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nSec-Fetch-Site: cross-site\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Dest: document\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'
- 想让客户端(浏览器)收到服务端发送的数据,需要遵循HTTP协议,因此在给客户端回复消息的时候必须按照HTTP协议规则加上响应状态行
低配版自定义web框架--遵循HTTP协议
# 你可以将web框架理解成服务端
import socket
server = socket.socket()
server.bind(("127.0.0.1",8080))
server.listen(5)
while True:
conn,addr = server.accept()
data = conn.recv(1024)
print(data)
data = data.decode("utf-8")
conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
conn.send(b"hello web")
conn.close()
中配版自定义web框架---根据不同的url返回不同的内容
- 低配版 ----if判断
原理:将浏览器发送到服务端的数据进行处理,然后做一个判断即可
b'GET /index HTTP/1.1\r\n
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n
Sec-Fetch-Site: cross-site\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\r\n
Sec-Fetch-Dest: document\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n\r\n'
# 你可以将web框架理解成服务端
import socket
server = socket.socket()
server.bind(("127.0.0.1",8080))
server.listen(5)
while True:
conn,addr = server.accept()
data = conn.recv(1024)
current_path = data.decode("utf-8").split(" ")[1]
conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
if current_path =="/index":
conn.send(b"hello index")
elif current_path =="/login":
conn.send(b"hello login")
else:
conn.send(b"404 error")
conn.close()
中配版---使用函数与列表结合
低配版的问题:虽然解决了不同url路径返回不同内容的需求,但是如果有很多路径要判断怎么办?难道挨个写if判断?
# 你可以将web框架理解成服务端
def index():
return "hello index"
def login():
return "hello login"
def error():
return "404 error"
urls = [
("/login",login),
("/index",index),
]
import socket
server = socket.socket()
server.bind(("127.0.0.1",8080))
server.listen(5)
while True:
conn,addr = server.accept()
data = conn.recv(1024)
current_path = data.decode("utf-8").split(" ")[1]
conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
func = None
for url in urls:
if current_path ==url[0]:
func = url[1]
break
if func:
ret = func()
else:
ret = error()
conn.send(ret.encode("utf-8"))
conn.close()
上面的代码的不足之处
1.代码重复(服务端代码所有人都要重复写)
2.手动处理http格式的数据 并且只能拿到url后缀 其他数据获取繁琐(数据格式一样处理的代码其实也大致一样 重复写)
3.并发的问题
基于wsgiref模块
from wsgiref.simple_server import make_server
def index(env):
return 'index'
def login(env):
return "login"
def error(env):
return '404 error'
# url与函数的对应关系
urls = [
('/index',index),
('/login',login),
]
def run(env,response):
'''
:param env: 请求相关的所有数据
:param response: 响应相关的所有数据
:return: 返回浏览器的数据
'''
# print(env) #大字典 wsgiref模块帮你处理好http格式的数据 封装成了字典让你更加方便的操作
# 从env中取
response("200 OK",[]) # 响应首行 响应头
current_path = env.get("PATH_INFO")
# 定义一个变量 存储匹配到的函数名
func = None
for url in urls:
if current_path == url[0]:
# 将url对应得函数名赋值给func
func = url[1]
break # 匹配到一个之后 应该立刻结束for循环
# 判断func是否有值
if func:
res = func(env)
else:
res = error(env)
return [res.encode("utf-8")]
if __name__ =="__main__":
server = make_server("127.0.0.1",8080,run)
"""
会实时监听127.0.0.1:8080地址 只要有客户端来了
都会交给run函数处理(加括号触发run函数的运行)
fladk启动源码
make_server("127.0.0.1",8080,obj)
__call__
"""
server.serve_forever() # 启动服务端
代码拆分及主要文件说明
urls.py文件
from views import *
# url与函数的对应关系
urls = [
('/index',index),
('/login',login),
]
views.py文件
def index(env):
return 'index'
def login(env):
return "login"
def error(env):
return '404 error'
基于wsgiref模块
from wsgiref.simple_server import make_server
from urls import urls
from views import *
def run(env, response):
response('200 OK', []) # 响应首行 响应头
current_path = env.get('PATH_INFO')
func = None
for url in urls: # url (),()
if current_path == url[0]:
# 将url对应的函数名赋值给func
func = url[1]
break # 匹配到一个之后 应该立刻结束for循环
# 判断func是否有值
if func:
res = func(env)
else:
res = error(env)
return [res.encode('utf-8')]
if __name__ == '__main__':
server = make_server('127.0.0.1',8080,run)
server.serve_forever() # 启动服务端
文件说明:
urls.py 路由与视图函数对应关系
view.py 视图函数(后端业务逻辑)
templates文件夹 专门用于存储html文件
按照功能的不同拆分之后 后续添加功能只需要在urls.py书写对应关系 然后去views.py书写业务逻辑即可
返回html文件
urls.py文件
from views import *
# url与函数的对应关系
urls = [
('/index',index),
('/login',login),
("/html",html)
]
views.py文件
def index(env):
return 'index'
def login(env):
return "login"
def html(env):
with open("html.html","r",encoding = "utf-8") as f:
data = f.read()
return data
def error(env):
return '404 error'
基于wsgiref模块
from wsgiref.simple_server import make_server
from urls import urls
from views import *
def run(env, response):
response('200 OK', []) # 响应首行 响应头
current_path = env.get('PATH_INFO')
func = None
for url in urls: # url (),()
if current_path == url[0]:
# 将url对应的函数名赋值给func
func = url[1]
break # 匹配到一个之后 应该立刻结束for循环
# 判断func是否有值
if func:
res = func(env)
else:
res = error(env)
return [res.encode('utf-8')]
if __name__ == '__main__':
server = make_server('127.0.0.1',8080,run)
server.serve_forever() # 启动服务端
- 动静态网页
静态网页
页面上的数据是直接写死的 万年不变
动态网页
数据是实时获取的
eg:
1.后端获取当前时间展示到html页面上
2.数据是从数据库中获取的展示到html页面上
动态网页制作:后端获取当前时间展示到html页面上
import datetime
def get_time(env):
current_time = datetime.datetime.now().strftime("%Y-%m-%d %X")
#如何将后端获取的数据传递给前端html文件
with open("mytime.html","r",encoding="utf-8") as f:
data = f.read()
# data 就是一堆字符串
data = data.replace("wdefewfew",current_time) # 在后端将html页面处理好之后再返回给前端
return data
模版语法
原理:
- 模版的原理就是字符串替换,只要在HTML页面中遵循jinja2的语法规则书写,内部就会按照指定的语法进行替换
模版语法案例一
#注意要将该函数与路由对应关系加入到urls.py
from jinja2 import Template
def get_dict(env):
user_dict ={"username":"jason","age":18,"hobby":"read"}
with open(r"templates/04 get_dict.html","r",encoding=
"utf-8") as f:
data = f.read()
tmp = Template(data)
res = tmp.render(user_dic)
#给get_dict.html传递一个值 页面上通过变量名user就能够拿到user_dict,变量名是随意的,不过要见名知意
return res
#get_dict
<body>
{{xx}} //获取字典
//获取字典中的值的三种方式
{{xxx.get("username")}}
{{xxx["password"]}}
{{xxx.hobbies}}
</body>
- 模版语法案例二----后端数据库中数据展示到前端页面
def get_mysql(env):
conn = pymysql.connect(
host = "127.0.0.1",
port = 3306,
user = "root",
password = "123",
database = "user",
charset = "utf8"
autocommit = True
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql = "select * from info;"
rows = cursor.execute(sql)
data_list = cursor.fetchall()
with open(r"template/get_mysql.html","r",encoding="urf-8") as f:
data = f.read()
temp = Template(data)
res = temp.render(data_list=data_list)
return res
自定义简易版本web框架流程图
wsgiref
1.请求来的时候解析http格式的数据 封装成大字典
2.响应走的时候给数据打包成符合http格式 再返回给浏览器
web框架推导的更多相关文章
- 自定义web框架(django)
Django基础了解知识 HTTP协议(超文本传输协议) HTTP协议 四大特性: 基于TCP/IP之上作用于应用层 基于请求响应 无状态 引申出cookie session token-- 无连接 ...
- Web开发框架推导
本文欲回答这样一个问题:在 「特定环境 」下,如何规划Web开发框架,使其能满足 「期望 」? 假设我们的「特定环境 」如下: 技术层面 使用Java语言进行开发 通过Maven构建 基于Spring ...
- Django-手撸简易web框架-实现动态网页-wsgiref初识-jinja2初识-python主流web框架对比-00
目录 自己动手实现一个简易版本的web框架 手撸一个web服务端 根据请求 url 做不同的响应处理 基于wsgiref模块实现服务端 用wsgiref 模块的做的两件事 拆分服务端代码 支持新的请求 ...
- 自创Web框架之过度Django框架
目录 自创Web框架之过度Django框架 软件开发架构 HTTP协议 Web框架之"撸起袖子加油干" Web框架之通过wsgiref加油干 封装优化处理 动静网页 jinjia2 ...
- Python(九)Tornado web 框架
一.简介 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过 ...
- 转-基于NodeJS的14款Web框架
基于NodeJS的14款Web框架 2014-10-16 23:28 作者: NodeJSNet 来源: 本站 浏览: 1,399 次阅读 我要评论暂无评论 字号: 大 中 小 摘要: 在几年的时间里 ...
- 初步认识Node 之Web框架
上一篇我们认识了Node是什么之后,这一篇我们主要了解的就是它的框架了.而它的框架又分为两大类,Web框架和全栈框架,接下来我们一个一个的来了解. Web框架 Web框架可以细分为Web应用程序 ...
- 【原】Go语言及Web框架Beego环境无脑搭建
本文涉及软件均以截至到2013年10月12日的最新版本为准 1. 相关软件准备: 1) go1.2rc1.windows-386.msi,对应32位windows系统安装使用 下载地址: https: ...
- 【译】什么是 web 框架?
Web 应用框架,或者简单的说是“Web 框架”,其实是建立 web 应用的一种方式.从简单的博客系统到复杂的富 AJAX 应用,web 上每个页面都是通过写代码来生成的.我发现很多人都热衷于学习 w ...
随机推荐
- 在vue项目中使用scss
1.首先安装依赖 npm install node-sass sass-loader --save-dev 2.找到build中webpack.base.conf.js,在rules中添加scss规则 ...
- android 申请忽略电池节电
fun checkBattery(){ var main = activity as MainActivity if(main.isIgnoringBatteryOptimizations()){ L ...
- NGINX 命令 重启 WINDOWS
最近系统更新比较频繁,web系统老是上新,因此在nginx这边经常需要重启或者刷新,做了一个批命令供参考. 1.鼠标右键-新建-一个.TXT文本文档:在里面输入NGINX重启的命令. 2.输入NGIN ...
- String painter (区间dp)
There are two strings A and B with equal length. Both strings are made up of lower case letters. Now ...
- 求学生单科流水表中单科最近/最新的考试成绩表的新增可行性方案 使用Oracle提供的分析函数rank
在 https://www.cnblogs.com/xiandedanteng/p/12327809.html 一文中,提到了三种求学生单科最新成绩的SQL可行性方案,这里还有另一种实现,那就是利用分 ...
- 2020重新出发,NOSQL,MongoDB分布式集群架构
MongoDB分布式集群架构 看到这里相信你已经掌握了 MongoDB 的大部分基本知识,现在在单机环境下操作 MongoDB 已经不存在问题,但是单机环境只适合学习和开发测试,在实际的生产环境中,M ...
- js去掉最右边的逗号
str=(str.substring(str.length-1)==',')?str.substring(0,str.length-1):str;
- 循序渐进VUE+Element 前端应用开发(20)--- 使用组件封装简化界面代码
VUE+Element 前端应用,比较不错的一点就是界面组件化,我们可以根据重用的指导方针,把界面内容拆分为各个不同的组合,每一个模块可以是一个组件,也可以是多个组件的综合体,而且这一个过程非常方便. ...
- PHP 类的构造方法 __construct()
1. 构造方法简介 构造方法 __construct() 是一种类结构特有的特殊方法,该方法由系统规定好 实例化一个类时:先调用该方法,再返回类的对象 构造方法也是普通方法,不同之处就是在实例化类时会 ...
- python中使用cookie进行模拟登录
背景:使用cookie模拟登录豆瓣->我的豆瓣网页 [准备工作] 1.通过Fiddler抓取“我的豆瓣”url: 2.通过Fiddler抓取“我的豆瓣”cookie值. import urlli ...