Django推导Django内部模块:wsgiref与jinja2
Django框架引导:推导过程
# 在了解Django框架之前先来研究一些其他的知识点,进而推导出什么是Django框架。
web应用
# 什么是web应用:
应用:我们通常将我们计算机的软件称为应用,像qq,微信,爱奇艺等,这些都称之为应用
web应用:只要是通过浏览器访问的应用都是web应用。
# (比如:通过浏览器访问爱奇艺,通过浏览器访问淘宝。)
# 软件开发架构:
服务端需要具备的特征:24小时对外提供服务
C/S:client:客户端 server:服务端
B/S:browser:浏览器 server:服务端
# 本质上B/S架构也是C/S架构
# Web应用程序的优点:
1. 无需将客户端软件下载安装到本地,只需要一个浏览器(百度 谷歌..)即可
2. 节省资源
3. 客户端不需要主动更新,服务端更新即可。
# Web应用程序的缺点:
1. 一旦服务端出现的问题,那么客户端将立马收到影响
2. 兼容性问题(在不同的浏览器可能会产生不同的影响) # 比如IE浏览器
那么作为程序员的我们web应用我们应该怎么部署呢?我们来一步步的探讨
手撸web框架
补充:
http的默认端口号:80 # 数据传输是明文的
https的默认端口号:443 # 数据传输是密文的
# web框架可以理解为服务端 现在我们自己手动写一个web服务端
import socket
server = socket.socket() #创建socket模块 默认就是基于网络的TCP传输协议
server.bind(('127.0.0.1',8080)) # 绑定ip和port 127.0.0.1为本地回环地址
server.listen(5) # 半连接池
while True:
conn, addr = server.accept() # 与客户端建立连接 等待接听
data = conn.recv(1024) # 接受客户端数据指定最大为1024字节
data = data.decode('utf8') # 解码转成字符类型(变为字符串)
conn.send(b'HTTP/1.1/ 200 OK\r\n\r\n') # 通过浏览器访问就必须遵循http协议,写在这里是通过tcp的流式协议来与后面的内容做匹配
# 如何做到后缀的不同返回不同的内容:
# data拿到的是用户请求的所有信息(那么用户输入的后缀就在以空格分割的第二个位置)
suffix_path = data.split(' ')[1] # 以空格切割字符串并取到索引1 索引1及为url的后缀
if suffix_path == '/index': # 后缀为index时给客户端传输index
conn.send(b'index')
elif suffix_path == '/login': # 后缀为login时给客户端传输login
conn.send(b'login')
else: # 在无后缀的情况
with open(r'myhtml.html','rb') as f: # 同样可以导入一个html文件并传输实现手撸web框架
conn.send(f.read()) # 给客户端返回一个html页面
conn.close() # 交互结束
弊端:
# 我们自己手撸的web框架的不足之处
1、 代码重复(在没写一个web服务端的时候服务端代码都要重复的写(创建链接等等))
2、 手动处理http格式的数据,并且只能拿到url后缀,其他数据获取繁琐(想要获取其他数据处理方式也大致一样,但是这样也就出现了重复的问题)
3、并发的问题(无法同时接收多个客户的请求)
# 那么怎么解决这些问题呢这就要用到wsgiref模块来帮助我们实现(让别人帮助我们撸)
wsgiref基本使用
WSGI(Web Server Gateway Interface 规范)
服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。
对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。
这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,
那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,
框架也可以使用更多支持标准的服务器。
WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序
与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。
常用的WSGI服务器有uWSGI、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,
Django开发环境用的就是这个模块来做服务器
wsgiref模块:
Python标准库提供的独立WSGI服务器叫wsgiref (主要要用开发测试使用,效率较低)
# 在看wsgiref模块之前我们来自己手动写一个web框架来对比看一下效果
wsgiref模块基本使用
启动文件run.py代码块
from wsgiref.simple_server import make_server
from urls import urls # 导入urls.py
from views import *
# env是wsgiref模块处理好的http格式的数据,封装成了字典让用户更加方便的操作
def run(env,response): # env:请求相关的所有数据 response响应相关的数据 return :返回给浏览器的数据
response('200 OK', []) # 响应首行和响应头 返回的格式
current_path = env.get('PATH_INFO') # 从env中可根据PATH_INFO找到url后缀
func = None # 定义一个变量,存储匹配到的函数名
for url in urls:
if current_path == url[0]: # 去索引0拿到的是元组的第一个元素
func = url[1] # 将url对应的函数名赋值给func
break # 匹配到一个就结束循环(节省内存)
if func: # 如果func有值说明匹配到了 然后执行对应的函数 并且把env(用户请求的相关信息)传参过去用以函数做处理
res = func(env)
else: # 如果没有匹配到说明没有写对应后缀的逻辑代码块
res = error(env) # 返回一个报错页面或者跳转页面给用户。
return [res.encode('utf8')] # 统一编码函数的返回值 并返回给用户
if __name__ == '__main__':
server = make_server('127.0.0.1',8080,run) # 实时监听(127.0.0.1:8080) 只要有客户端来(无论有什么后缀) 触发run函数运行run(env,response)并且给run函数传了两个参数(env,response) ,如果放的不是函数放的是对象,那么同样会给对象()执行产生对象类里面的__call__方法
server.serve_forever() # 启动服务端
# 这个里面的功能就不需要更改了,如果有新的功能只需要写下述代码块就可以(这样写不会是代码冗余,每一个py文件就写一个功能。)
urls.py代码块
# 存储路由(url后缀)与视图函数对应(主要的后端业务逻辑)关系
from views import *
urls = [('/index',index),
('/login',login),
('/xxx',xxx),
('/gettime',gettime)]
views.py代码块
# 该板块存储主要的业务逻辑
def index(env):
return 'index'
def login(env):
return 'login'
def error(env):
return '404 error'
def xxx(env): # 同样可以返回html文件
with open(r'templates/myhtml.html', 'r', encoding='utf8') as f:
return f.read()
import datetime
def gettime(env):
current_time = datetime.datetime.now().strftime('%Y-%m-%d %X')
# 如何将后端获取到的时间数据传递给html文件
with open(r'templates/mytime.html','r',encoding='utf8') as f:
data = f.read()
data = data.replace('time',current_time) # 在后端处理好数据后返回给前端
return data
总结:
urls.py # 存储路由与视图函数对应关系
views.py # 存储视图函数(后端业务逻辑)
templates文件夹 # 专门用来存储html文件
# 按照功能的不同拆分之后,后续添加功能只需要
# 在urls.py书写对应关系
# 在views.py书写主要的业务逻辑即可
动静态网页
# 静态网页:
页面上的数据是直接写死的,在人为不去后台修改的情况下,永远不会改变。
# 动态网页:
比如:
1.后端获取当前时间展示到html页面上
2.数据是从数据库中获取的展示到html页面上
# 这些需要实施获取的都属于动态网页
动态页面示例:
urls.py
urls = [('/gettime',gettime)]
views.py
import datetime
def gettime(env):
current_time = datetime.datetime.now().strftime('%Y-%m-%d %X') #
# 如何将后端获取到的时间数据传递给html文件
with open(r'templates/mytime.html','r',encoding='utf8') as f:
data = f.read()
data = data.replace('time',current_time) # 在后端处理好数据(替换字符串)后返回给前端
return data
mytime.html
<h1>动态模块</h1>
time
给html文件添加字典操作:
# 需求:将一个字典传递给html文件 并且可以在文件上方便快捷的操作字典数据
这里需要用到一个'Jinja2'模块:jinja2为第三方模块需要手动下载
urls.py
urls = [('/getdict',get_dict)]
views.py
from jinja2 import Template
def get_dict(env):
user_dic = {'username':'gary','age':19,'hobby':'basketball'}
with open(r'templates/get_dict.html','r',encoding='utf8') as f:
data = f.read()
tmp = Template(data)
res = tmp.render(user=user_dic) # 给html页面传递了一个值,页面上可通过变量名user就能够拿到user_dict
return res
get_html.html
<body>
<h1>我是一个可操作字典</h1>
{{ user }} <!--jinja2提供的模板语法(非常贴近python语法)是在后端起作用的-->
<p>
{{ user.get('username') }} <!--可使用字典的方法取值-->
{{ user.age }}
{{ user['hobby'] }}
</p>
</body>
后端获取数据库中的数据展示到前端页面
urls.py
urls = [('/getuser',get_user)]
views.py
import pymysql
def get_user(env):
# 去数据库中获取数据 传递给
conn = pymysql.connect(
host='127.0.0.1',
port = 3306,
user = 'root',
password= '123',
db='user',
charset='utf8',
autocommit =True
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql = 'select * from userinfo'
affect_rows = cursor.execute(sql)
data_list = cursor.fetchall()
# 将获取到的数据传递给html文件
with open(r'templates/get_data.html','r',encoding='utf8') as f:
data = f.read()
tmp = Template(data)
res = tmp.render(user_list = data_list)
return res
#
html
<!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">
<div class="col-md-8 col-md-offset-2">
<h1 class="text-center">用户数据</h1>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>ID</th>
<th>username</th>
<th>age</th>
<th>hobby</th>
</tr>
</thead>
<tbody>
{% for user_dict in user_list%}
<tr>
<td>{{ user_dict.id }}</td>
<td>{{ user_dict.username}}</td>
<td>{{ user_dict.age}}</td>
<td>{{ user_dict.hobby}}</td>
</tr>
{% endfor%}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
上述我们自己使用不同的模块来推导出来的web框架流程有现成的别人写好的框架来供我们使用:我们只需要在固定的位置编写固定的代码即可
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)