自创Web框架之过度Django框架

Web框架,其实就是Web应用的建立;比如网页版的QQ,b站····都是Web应用软件;

Web应用又是什么?可以理解为基于浏览器的一些应用程序,用户只需要有浏览器即可,不需要再安装其他软件;

比如我们打开一个URL,Web服务器返回一个HTML页面给你,那么你在搜索或者URL拼接路径搜索的时候Web服务器是怎么知道要返回什么给你?下面介绍一下:

在介绍之前先介绍所需基础知识,同时也是Web运行所需的:

[Web基础知识](Web入门 - HammerZe - 博客园 (cnblogs.com))

软件开发架构

  • C/S架构:客户端和服务端
  • B/S架构:浏览器和服务端

ps:b/s本质也是c/s架构

HTTP协议

四大特性

  • 基于TCP、IP作用于应用层之上的协议
  • 基于请求响应
  • 无状态
  • 无(短)连接
    • 长连接:websocket

数据格式

请求首行(http协议版本,网络请求的方法)
请求头(一大堆k,v键值对)
/r/n # 换行符不能省略
请求体(存放的是一些数据,并不是每种请求方式都有请求体,get没有请求体,post有请求体) # 请求方式
get:朝服务器索要数据,比如输入网址获得相应的数据
post:向服务器提交数据,比如用户登录输入用户名和密码后,提交到后端做身份校验

响应格式

响应首行(http协议版本,网络请求的方法)
响应头(一大堆k,v键值对)
/r/n # 换行符不能省略
响应体(交给给浏览器展示给用户看的数据)

响应状态码

HTTP 状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型。响应分为五类:信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误 (500–599)

分类 分类描述
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误
# 注意
公司还会自定义状态码 一般以10000开头
参考:聚合数据

请求方式

  • get请求:向别人(服务器)索要数据
  • post请求:向别人提交数据(比如表单)

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) # 忽略favicon.ico,拿到用户在url后面输入的字符串
data = data.decode('utf-8')
conn.send(b'HTTP/1.1 200 Ok\r\n\r\n')
# 获取字符串中特定的内容 正则和切割
current_path = data.split(' ')[1]
# print(current_path) # /index
if current_path =='/index':
with open(r'E:\web组件\图书管理系统界面\图书管理系统.html','rb')as f:
conn.send(f.read())
elif current_path == '/login':
conn.send(b'hello')
else:
conn.send(b'Nothing to give you!')
conn.close()

通过上面的例子,能够简单的理解通过get请求方式得到的页面是如何返回,但是我们个人手写得服务端存在问题,如果客户请求不同得页面那么我们就得写n多个if/else,数据得格式处理起来也比较繁琐······通过一个模块来解决这些问题wsgiref模块

Web框架之通过wsgiref加油干

# 解决了上述两个问题
from wsgiref.simple_server import make_server def run(request,response):
"""
:param request:请求相关的所有数据
:param response:响应相关的所有数据
:return:返回给浏览器的数据
"""
response('200 OK',[])
current_path = request.get("PATH_INFO")
if current_path == '/index':
return [b'index']
elif current_path == '/login':
return [b'login']
return [b'404 error'] if __name__ == '__main__':
server = make_server('127.0.0.1',8080,run) # 实时监听,一旦被访问会全部交给run函数处理
server.serve_forever() # 启动服务端

封装优化处理

封装的过程中主要解决:

网址的匹配问题

网址多匹配如何解决

功能复杂代码块如何解决,放在一个文件结构不清晰

'''服务端'''
from wsgiref.simple_server import make_server
from views import *
from urls import *
'''
urls.py 路由与视图函数的对应关系
views.py主要存视图函数
templates 文件夹主要存HTML文件
拆分功能后只需在urls.py中书写对应关系,views.py中书写后端的业务逻辑即可
''' def run(env, response):
''' :param env:请求相关的所有数据
:param response:响应相关的所有数据
:return:返回给浏览器的数据
'''
# print(env) # wsgiref 模块 将http格式的数据处理好
response('200 ok',[])
# 从env返回的大字典中拿出用户输入的内容 --->key
current_path = env.get('PATH_INFO')
# if current_path == '/index':
# return [b'Hell index']
# elif current_path == 'login':
# return [b'hello wsgiref']
# else:
# return [b'404'] # 定义一个变量存储匹配到的函数名
func = None
for url in urls:
if current_path == url[0]:
# 匹配成功将url对应的函数名赋值给func
func = url[1]
break # 结束当前循环
# 判断一下func是否有值
if func:
res = func()
else:
res = error()
return [res.encode('utf-8')] if __name__ == '__main__':
server = make_server('127.0.0.1', 8081, run) # 实时监听,只要有客户端来了,就交给run函数执行
server.serve_forever() # 启动服务端
'''
urls.py 路由与视图函数的对应关系 '''
from views import * urls = [
('/index',index),
('login',login)
]
'''
views.py主要存视图函数
下面统称为视图函数 ''' def index(env):
return 'index'
def login(env):
return 'login'
def error(env):
return '404'
# 返回文件
def file(env):
with open(r'E:\web组件\图书管理系统界面\图书管理系统.html','r',encoding='utf8')as f:
return f.read()

动静网页

  • 静态网页:数据是不变的,不需要实时变化的,数据写死··
  • 动态网页:数据来源于后端(代码、数据库),数据实时变化等特点

示例一:将时间同步到html页面

'''服务端'''
from wsgiref.simple_server import make_server from urls import *
def run(env, response):
''' :param env:请求相关的所有数据
:param response:响应相关的所有数据
:return:返回给浏览器的数据
'''
# print(env) # wsgiref 模块 将http格式的数据处理好
response('200 ok', [])
# 从env返回的大字典中拿出用户输入的内容 --->key
current_path = env.get('PATH_INFO') # 定义一个变量存储匹配到的函数名
func = None
for url in urls:
if current_path == url[0]:
# 匹配成功将url对应的函数名赋值给func
func = url[1]
break # 结束当前循环
# 判断一下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', 8081, run) # 实时监听,只要有客户端来了,就交给run函数执行
server.serve_forever() # 启动服务端 '''urls.py'''
from views import * urls = [
('/get_time',get_time),
] '''views.py'''
# 同步时间
def get_time(env):
from datetime import datetime
current_time = datetime.now().strftime('%Y-%m-%d %X')
with open(r'get_time.html','r',encoding='utf8') as f:
data = f.read()
data = data.replace('AAA',current_time) # 用替换的方式将数据传到HTML文件中
return data
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<style>
#d1{
font-size: 48px;
color: tomato; }
</style>
<body> <div class="container">
<div class="row">
<div id="d1" class="col-md-8 col-lg-offset-2">
AAA
</div>
</div>
</div>
</body>
</html>

jinjia2模块

该模块是flask框架必备的模块,在这里只使用jinjia2模块来写我们的模板语法

需求:将后端字典展示到HTML页面上

'''服务端和上面一样'''

'''urls.py'''
from views import *
urls = [
('/get_dict',get_dict)
]
'''views.py''' # 获取字典
def get_dict(env):
user_dict = {'id': 1, 'name': 'Hammer', 'hobby': 'python'}
from jinja2 import Template
with open(r'templates/get_dict.html', 'r', encoding='utf8') as f1:
data = f1.read()
temp = Template(data)
res = temp.render(user_data=user_dict) # 将user_dict传递给html页面,在该页面使用user_data调用
return res
<!--由于导入了jinjia2模块,这里可以直接使用模板语法,类似python的字典方法-->
<body>
{{user_data}}
{{user_data.id}}
{{user_data['name']}}
{{user_data.get('hobby')}}
</body>

数据库

需求:操作MySQL数据并且展示到HTML页面上

注意:数据是在后端处理完之后发送到前端的

'''服务端'''
from wsgiref.simple_server import make_server from urls import *
def run(env, response):
''' :param env:请求相关的所有数据
:param response:响应相关的所有数据
:return:返回给浏览器的数据
'''
# print(env) # wsgiref 模块 将http格式的数据处理好
response('200 ok', [])
# 从env返回的大字典中拿出用户输入的内容 --->key
current_path = env.get('PATH_INFO') # 定义一个变量存储匹配到的函数名
func = None
for url in urls:
if current_path == url[0]:
# 匹配成功将url对应的函数名赋值给func
func = url[1]
break # 结束当前循环
# 判断一下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', 8081, run) # 实时监听,只要有客户端来了,就交给run函数执行
server.serve_forever() # 启动服务端
'''路由'''
from views import *
urls = [
('/get_db',get_db)
]
'''视图函数'''
# 获取数据库的内容
def get_db(env):
import pymysql
conn = pymysql.connect(
user='root',
password='7410',
port=3306,
host='127.0.0.1',
database='info',
charset='utf8',
autocommit=True
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql = 'select * from emp;'
rows = cursor.execute(sql)
res = cursor.fetchall() # [{},{},{}]
# print(res)
with open(r'templates/get_db.html','r',encoding='utf8') as f:
data = f.read()
temp = Template(data)
total_res = temp.render(data_list = res)
return total_res
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<h1 style="text-align: center">用户数据</h1>
<div class="col-md-8 col-lg-offset-2">
<table class="table table-striped table-hover ">
<thead>
<tr class="success" style="text-align: center">
<td>id</td>
<td>name</td>
<td>sex</td>
<td>age</td>
<td>dep_id</td>
</tr>
</thead>
<tbody>
{%for user_dict in data_list%}
<tr class="info" style="text-align: center">
<td>{{user_dict.id}}</td>
<td>{{user_dict.name}}</td>
<td>{{user_dict.sex}}</td>
<td>{{user_dict.age}}</td>
<td>{{user_dict.dep_id}}</td>
</tr>
{%endfor%}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>

到此前后端和数据库交互就都完成了,这所有的功能都可以用Django完成,上面只是一个推导过程~


自写框架梳理

  • wsgiref模块:

    • 封装了socket代码
    • 处理了http数据格式
  • 根据功能的不同拆分成不同的文件夹
    • urls.py 路由与视图函数对应关系
    • views.py 视图函数
    • templates 模板文件夹
  • 步骤:
    • 第一步添加路由与视图函数的对应关系
    • 去views中书写功能代码
    • 如果需要使用到html则去模板文件夹中操作
  • jinjia2模板语法
    • {{}}
    • {%%}

自创Web框架之过度Django框架的更多相关文章

  1. python主流框架简介和Django框架的使用

    目录 一.手撸简易web框架 二.动静态网页 1. 静态网页 2. 动态网页 三.jinja2模板语法 1. jinja2的作用 四.python主流web框架 1. django 3. tornad ...

  2. DRF框架之使用Django框架完成后端接口(API)的定义

    学习DRF框架,首先我们就需要明白为什么要学习这个框架. 接下来我们就先用原生的Django框架来定义一个符合RESTful设计方法的接口(API). RESTful接口的需求如下: GET /boo ...

  3. Django框架01 / http协议、web框架本质

    Django框架01 / http协议.web框架本质 目录 Django框架01 / http协议.web框架本质 1.http协议 1.1 http协议简介 1.2 什么是http协议 1.3 H ...

  4. Pyhton-Web框架之【Django】

    一.什么是web框架 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. 对于所有的 ...

  5. 第三百零三节,Django框架介绍——用pycharm创建Django项目

    Django框架介绍 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的软件设计模式,即模型M,视图V和控制器C.它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内 ...

  6. 一 Django框架介绍——用pycharm创建Django项目

    Django框架介绍 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的软件设计模式,即模型M,视图V和控制器C.它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内 ...

  7. Django框架——基础教程(总)

    1. Django简介 Python下有许多款不同的 Web 框架.Django是重量级选手中最有代表性的一位.许多成功的网站和APP都基于Django. Django是一个开放源代码的Web应用框架 ...

  8. Django 框架之前

    返回主目录:Django框架 内容目录: 一.Django框架之前的内容 1.1 web应用程序的架构 1.2 HTTP协议 1.3 纯手写简单web框架 一.Django框架之前d的内容 1.1 w ...

  9. WEB框架-Django框架学习-预备知识

    今日份整理,终于开始整个阶段学习的后期了,今日开始学习Django的框架,加油,你是最胖的! 1.web基础知识 1.1 web应用 Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是 ...

随机推荐

  1. HUAWEI网络设备恢复Console口密码

    密码遗忘 本章介绍了Console口丢失的处理方法,建议用户妥善保管密码,并定期修改. 恢复Console口密码 设备提供如下方法恢复Console口密码.•方法一:通过STelnet/Telnet登 ...

  2. k个鸡蛋从N楼层摔,如果确定刚好摔碎的那个楼层,最坏情况下最少要试验x次?

    题目 k个鸡蛋从N楼层摔,如果确定刚好摔碎的那个楼层,最坏情况下最少要试验x次? 换个说法: k个鸡蛋试验x次最多可以检测N层楼.计算出N? 逆向思维和数学公式解. 分析 定义N(k,x) 如果第k个 ...

  3. Solon Web 开发,十四、与Spring、Jsr330的常用注解对比

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  4. Git命令中波浪号~与脱字符^的区别

    0.前言 波浪号~,英文名叫 tilde.脱字符^,英文名叫caret. 这两种符号常见于git reset的情景,简单的项目结构和操作一般不会涉及到两者之间的区别,似乎用哪个都可以.如果遇到比较繁杂 ...

  5. WebGPU图形编程(3):构建三角形图元<学习引自徐博士教程>

    一.首先修改你的index.html文件 请注意主要在html页面修改添加的是需要加选择项:"triangle-list"和"triangle-strip",如 ...

  6. golang中的udp编程

    1. udp server package main import ( "fmt" "net" ) func main() { // udp server li ...

  7. python数据操作--8

    转:https://www.tuicool.com/wx/MB7nieb 数据类型 整数, 浮点数, 字符串, 布林值(True,False) 列表(list), 不可变的列表 Tuple, 集合(没 ...

  8. grafana ldap 权限无法保持

    一.Grafana介绍 Grafana是一个跨平台的开源的度量分析和可视化工具,可以通过将采集的数据查询然后可视化的展示,并及时通知.它主要有以下六大特点: 1.展示方式:快速灵活的客户端图表,面板插 ...

  9. k8s基本概念,资源对象

    kubernetes里的master指的是集群控制节点 master负责是整个集群的管理和控制 kubernetes3大进程 API server 增删改查操作的关键入口 controller man ...

  10. jsp FN 标签库的使用方法

    1.   在jsp  导入标签库 <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="f ...