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框架推导的更多相关文章

  1. 自定义web框架(django)

    Django基础了解知识 HTTP协议(超文本传输协议) HTTP协议 四大特性: 基于TCP/IP之上作用于应用层 基于请求响应 无状态 引申出cookie session token-- 无连接 ...

  2. Web开发框架推导

    本文欲回答这样一个问题:在 「特定环境 」下,如何规划Web开发框架,使其能满足 「期望 」? 假设我们的「特定环境 」如下: 技术层面 使用Java语言进行开发 通过Maven构建 基于Spring ...

  3. Django-手撸简易web框架-实现动态网页-wsgiref初识-jinja2初识-python主流web框架对比-00

    目录 自己动手实现一个简易版本的web框架 手撸一个web服务端 根据请求 url 做不同的响应处理 基于wsgiref模块实现服务端 用wsgiref 模块的做的两件事 拆分服务端代码 支持新的请求 ...

  4. 自创Web框架之过度Django框架

    目录 自创Web框架之过度Django框架 软件开发架构 HTTP协议 Web框架之"撸起袖子加油干" Web框架之通过wsgiref加油干 封装优化处理 动静网页 jinjia2 ...

  5. Python(九)Tornado web 框架

    一.简介 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过 ...

  6. 转-基于NodeJS的14款Web框架

    基于NodeJS的14款Web框架 2014-10-16 23:28 作者: NodeJSNet 来源: 本站 浏览: 1,399 次阅读 我要评论暂无评论 字号: 大 中 小 摘要: 在几年的时间里 ...

  7. 初步认识Node 之Web框架

    上一篇我们认识了Node是什么之后,这一篇我们主要了解的就是它的框架了.而它的框架又分为两大类,Web框架和全栈框架,接下来我们一个一个的来了解.    Web框架 Web框架可以细分为Web应用程序 ...

  8. 【原】Go语言及Web框架Beego环境无脑搭建

    本文涉及软件均以截至到2013年10月12日的最新版本为准 1. 相关软件准备: 1) go1.2rc1.windows-386.msi,对应32位windows系统安装使用 下载地址: https: ...

  9. 【译】什么是 web 框架?

    Web 应用框架,或者简单的说是“Web 框架”,其实是建立 web 应用的一种方式.从简单的博客系统到复杂的富 AJAX 应用,web 上每个页面都是通过写代码来生成的.我发现很多人都热衷于学习 w ...

随机推荐

  1. 在vue项目中使用scss

    1.首先安装依赖 npm install node-sass sass-loader --save-dev 2.找到build中webpack.base.conf.js,在rules中添加scss规则 ...

  2. android 申请忽略电池节电

    fun checkBattery(){ var main = activity as MainActivity if(main.isIgnoringBatteryOptimizations()){ L ...

  3. NGINX 命令 重启 WINDOWS

    最近系统更新比较频繁,web系统老是上新,因此在nginx这边经常需要重启或者刷新,做了一个批命令供参考. 1.鼠标右键-新建-一个.TXT文本文档:在里面输入NGINX重启的命令. 2.输入NGIN ...

  4. String painter (区间dp)

    There are two strings A and B with equal length. Both strings are made up of lower case letters. Now ...

  5. 求学生单科流水表中单科最近/最新的考试成绩表的新增可行性方案 使用Oracle提供的分析函数rank

    在 https://www.cnblogs.com/xiandedanteng/p/12327809.html 一文中,提到了三种求学生单科最新成绩的SQL可行性方案,这里还有另一种实现,那就是利用分 ...

  6. 2020重新出发,NOSQL,MongoDB分布式集群架构

    MongoDB分布式集群架构 看到这里相信你已经掌握了 MongoDB 的大部分基本知识,现在在单机环境下操作 MongoDB 已经不存在问题,但是单机环境只适合学习和开发测试,在实际的生产环境中,M ...

  7. js去掉最右边的逗号

    str=(str.substring(str.length-1)==',')?str.substring(0,str.length-1):str;

  8. 循序渐进VUE+Element 前端应用开发(20)--- 使用组件封装简化界面代码

    VUE+Element 前端应用,比较不错的一点就是界面组件化,我们可以根据重用的指导方针,把界面内容拆分为各个不同的组合,每一个模块可以是一个组件,也可以是多个组件的综合体,而且这一个过程非常方便. ...

  9. PHP 类的构造方法 __construct()

    1. 构造方法简介 构造方法 __construct() 是一种类结构特有的特殊方法,该方法由系统规定好 实例化一个类时:先调用该方法,再返回类的对象 构造方法也是普通方法,不同之处就是在实例化类时会 ...

  10. python中使用cookie进行模拟登录

    背景:使用cookie模拟登录豆瓣->我的豆瓣网页 [准备工作] 1.通过Fiddler抓取“我的豆瓣”url: 2.通过Fiddler抓取“我的豆瓣”cookie值. import urlli ...