10 分离式web框架
10 分离式web框架
wsgiref模块:
将http请求封装成以键值对的形式封装成字典environ:
"PATH_INFO"对应的值为请求文件路径,
“QUERY_STRING”对应的值为get请求发送的数据
“REQUEST+METHOD”对应的值为请求方式。
同时封装一个发送响应格式的函数start_server;通过特定的方式return [ ]返回数据并调用内置方法返回给浏览器。
GET和POST请求:
请求参数的获取:
GET请求参数的传递在url请求文件路径后边拼接显式传输,可以直接在wsgiref模块封装好的environ请求信息字典中以键“QUERY_STRING”取值获取传递的参数;
POST请求参数的传递是在请求信息的请求数据部分,
通过在wsgiref模块封装好的environ请求信息字典中以键“CONTENT_LENGTH”获取参数(bytes类型)长度,然后通过environ["wsgi.input"].read(长度)获取传递的参数(bytes类型)
请求参数的处理:
内置模块(from urllib.parse import parse_qs)
执行parse_qs()进行格式化成字典找到对应的参数值(列表形式,注意get为字符串,post为字节);
具体处理方式:
GET:
|
query_string=environ["QUERY_STRING"] |
#'QUERY_STRING': 'username=zhangsan&userpsd=abc', |
|
query_string=parse_qs(query_string) |
#{ 'username':['zhangsan'],'userpsd':['abc']} |
|
name=query_request["username"][0] |
'zhangsan' |
|
psd=query_request["userpsd"][0] |
'abc' |
POST:
|
leng=int(environ.get('CONTENT_LENGTH',0)) |
#'CONTENT_LENGTH'参数长度 |
|
query_string=environ['wsgi.input'].read(leng) |
#{ 'username':['zhangsan'],'userpsd':['abc']} |
|
query_string=parse_qs(query_string) |
#{ b'username':[b'zhangsan'],b'userpsd':[b'abc']} |
|
name=query_string[b'username'][0].decode("utf-8") |
'zhangsan' |
|
psd=query_string[b'userpsd'][0].decode("utf-8") |
'abc' |
wsgiref封装的请求信息:
|
GET |
{……. 'SERVER_PORT': '8888', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/auth', 'QUERY_STRING': 'username=zhangsan&userpsd=abc', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'text/plain', 'HTTP_HOST': '127.0.0.1:8888', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'wsgi.input': <_io.BufferedReader name=916>…….} |
|
POST |
{…… 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8888', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '29', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'REQUEST_METHOD': 'POST', 'PATH_INFO': '/auth', 'QUERY_STRING': '', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'wsgi.input': <_io.BufferedReader name=880>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>} |
客户端浏览器访问:
在浏览器地址栏直接输入地址端口:127.0.0.1:8888
服务器server端python程序(分离版本):

manege.py:
from wsgiref.simple_server import make_server #python内置基于socket的服务程序模块
from urls import func_mappers #自己封装的请求文件路径与对应操作映射模块 def application(environ,start_reponse):
"""
基于wsgiref模块实现客户端请求数据的封装(字典environ)和封装的响应格式发送函数(statr_response)进行服务响应
:param environ: wsgiref模块封装好的请求信息字典
:param start_reponse: wsgiref模块封装的响应格式发送函数
:return:
"""
path=environ["PATH_INFO"] #通过字典取值获取请求路径信息
start_reponse("200 Ok",[("Content","text/html")]) #分装好的函数发送响应格式信息
# print(path)
# 根据请求文件路径,映射与之对应的函数操作
for mapper in func_mappers:
if path==mapper[0]:
data=mapper[1](environ)
else:
data=b"Sorry:404 not find"
return [data] if __name__ == '__main__':
httpd=make_server("127.0.0.1",8888,application)
httpd.serve_forever()
manage.py
modles.py
# 连接数据库,创建需要实用的信息表
import pymysql
conn=pymysql.connect("127.0.0.1","root","","web")
cursor=conn.cursor() user=[("zhangsan","abc"),
("lisi","")]
sql_createTable="create table userinfo(uid int primary key auto_increment,name char(12) unique not null ,password char(32) not null )"
sql_insret="insert into userinfo(name,password) values" cursor.execute(sql_createTable) for data in user:
sql_value=sql_insret+str(data)
cursor.execute(sql_value)
conn.commit() cursor.close()
conn.close()
models.py
urls.py
# 路由信息:请求文件路径与对应操作函数的映射表
from views import *
func_mappers=[
("/",func_login),
("/auth",func_auth)]
uels.py
views.py
from urllib.parse import parse_qs #内置模块方法用于处理请求传递的数据格式
from webauth import auth # 客户端请求根目录时响应登录页面
def func_login(environ):
with open("login.html", "rb")as f:
data = f.read()
return data # 客户端提交登录时,判断请求方式,获取提交的数据,进行验证
def func_auth(environ): if environ.get("REQUEST_METHOD") == "GET":
query_request = environ["QUERY_STRING"]
# print(user)
# print(environ) query_request = parse_qs(query_request)
print(repr(query_request))
username = query_request["username"][0]
psd = query_request["userpsd"][0] elif environ.get("REQUEST_METHOD") == "POST":
# 获取请求体数据的长度,因为提交过来的数据需要用它来提取,注意POST请求和GET请求的获取数据的方式不同
try:
request_body_size = int(environ.get('CONTENT_LENGTH', 0))
except (ValueError):
request_body_size = 0
# POST请求获取数据的方式
request_data = environ['wsgi.input'].read(request_body_size)
print('>>>>>', request_data) # >>>>> b'username=chao&password=123',是个bytes类型数据
print('?????', environ['QUERY_STRING']) # ????? 空的,因为post请求只能按照上面这种方式取数据
# parse_qs可以帮我们解析数据
re_data = parse_qs(request_data)
print('拆解后的数据', re_data) # 拆解后的数据 {b'password': [b'123'], b'username': [b'chao']}
username=re_data[b'username'][0].decode("utf-8")
psd=re_data[b'userpsd'][0].decode("utf-8") # 获取用户名和密码之后进行提交验证
status = auth(username, psd)
if status:
with open("login_success.html", "rb")as f:
data = f.read()
else:
data = "<h1> login error</h1>".encode("utf-8")
return data
views.py
webauth.py
# 登录认证使用:连接数据库查询用户名和密码进行检验
def auth(username,psd):
import pymysql
conn = pymysql.connect("127.0.0.1", "root", "", "web")
cursor = conn.cursor()
sql_select=f"select * from userinfo where name='{username}' and password='{psd}' "
# print(sql_select)
ret=cursor.execute(sql_select) #函数返回结果ret为匹配到的记录条数
cursor.close()
conn.cursor()
return ret
# print(auth('zhangsan','abc'))
webauth.py
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="faviron.ico">
<title>登录</title>
</head>
<body>
<div> <form action="auth" method="post" name="login"><!--以post请求方式auth验证--> <!--<form action="auth" method="get" name="login"><!–以get请求方式auth验证–>-->
<table>
<tr>
<td><label for="username">用户名</label></td>
<td><input type="text" name="username" id="username"></td>
</tr>
<tr>
<td> <label for="userpsd">密码</label></td>
<td><input type="password" name="userpsd" id="userpsd"></td>
</tr>
<tr>
<td ><input type="reset"></td>
<td ><input type="submit"></td>
</tr>
</table> </form>
</div>
</body>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script>
$(function () {
//在登录之前在客户端进行账号、密码初级判断
$("form[name='login']").submit (function () {
var name = $("#username").val();
var psd = $("#userpsd").val(); if (name == "" || psd == "") {
alert("用户名和密码不能为空!");
return false
}
})
})
</script>
</html>
login.html
login_success.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="">
<meta name="keywords" content="">
<style></style>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<link rel="stylesheet" href="">
<title>首页</title>
</head>
<body>
<div>
<h1>登录成功!</h1>
</div>
</body>
</html>
login_success.html
10 分离式web框架的更多相关文章
- 10款Web开发最佳的Python框架
Python是跻身于当代IT世界最流行和代码最高效的编程语言之一.Python框架能帮助你快速启动Web应用. 1.CubicWeb CubicWeb的最重要的功能是其代码的可重用性,由一个个代码单元 ...
- 2018年要学习的10大Python Web框架
通过为开发人员提供应用程序开发结构,框架使开发人员的生活更轻松.他们自动执行通用解决方案,缩短开发时间,并允许开发人员更多地关注应用程序逻辑而不是常规元素. 在本文中,我们分享了我们自己的前十大Pyt ...
- 转-基于NodeJS的14款Web框架
基于NodeJS的14款Web框架 2014-10-16 23:28 作者: NodeJSNet 来源: 本站 浏览: 1,399 次阅读 我要评论暂无评论 字号: 大 中 小 摘要: 在几年的时间里 ...
- 【原】Go语言及Web框架Beego环境无脑搭建
本文涉及软件均以截至到2013年10月12日的最新版本为准 1. 相关软件准备: 1) go1.2rc1.windows-386.msi,对应32位windows系统安装使用 下载地址: https: ...
- web框架django初探
Web框架介绍 一般会分为两部分:服务器程序和应用程序.服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理.应用程序则负责具体的逻辑处理.为了方便应用程序的开发,就出 ...
- 第三篇 基于.net搭建热插拔式web框架(重造Controller)
由于.net MVC 的controller 依赖于HttpContext,而我们在上一篇中的沙箱模式已经把一次http请求转换为反射调用,并且http上下文不支持跨域,所以我们要重造一个contro ...
- Python之Web框架Django
Python之Web框架: Django 一. Django Django是一个卓越的新一代Web框架 Django的处理流程 1. 下载地址 Python 下载地址:https://www.pyt ...
- 第一个web框架tornado
简介 tornado,是我学到的第一个web框架是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google ...
- web框架 之 Tornado
初识 Tornado : tornado web server 是使用python编写出来的一个轻量级.高可伸缩性和非阻塞IO的Web服务器软件,其特点是采用epoll非阻塞IO,相应快速,可处理数千 ...
随机推荐
- Python带你做个愉快的"动森"玩家! (超简单代码)
最近Switch上的<动物森友会>可谓是炙手可热,它几乎算是任天堂版的<模拟人生>了,它的最新游戏<集合啦!动物森友会>(以下称“动森”)在发售后,取得了不错的媒体 ...
- Decision tree——决策树
基本流程 决策树是通过分次判断样本属性来进行划分样本类别的机器学习模型.每个树的结点选择一个最优属性来进行样本的分流,最终将样本类别划分出来. 决策树的关键就是分流时最优属性$a$的选择.使用所谓信息 ...
- 【JAVA基础】07 面向对象2
1. 代码块的概述和分类 面试的时候会问,开发不用或者很少用 代码块概述 在Java中,使用 {} 括起来的代码被称为代码块. 代码块分类 根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态 ...
- Vue中的父子传值问题
个人网站 https://iiter.cn 程序员导航站 开业啦,欢迎各位观众姥爷赏脸参观,如有意见或建议希望能够不吝赐教! 好久没更博了,感觉下班后的时间莫名其妙就没有了,有了,了... 趁着端午放 ...
- python实现二分叉查找
*二分叉查找就是折半查找 比如12345这几个数字当中找2,他会先找到这五个数字中的中坚的那个与2进行比较,比如中间的3>2他就认为3以后的不用查找了,然后查找3左边的,即123,再把这个分半, ...
- python笔记 函数初识
1. 函数: 封装一个功能 def my_len(形参): -> def 声明定义一个函数 my_len 函数名命名规则同变量 ······ - ...
- Vim Configuration
安装原生态的Vim之后,界面是这样的: 行号,没有:自动缩进,没有:括号匹配,没有~ 为了我们使用的方便,进行一些基本的配置: sudo vim /etc/vim/vimrc 进入配置界面: 如下图进 ...
- 题目分享Y
题意:给出一个n个点n条边的图且不一定连通(原题面为每个节点出度为1),相邻节点不能同时被选,每个节点有其对应价值,求最多能获得多少价值?n<=1e6,val[i]<=1e6 分析:很容易 ...
- E. Count The Blocks
E. Count The Blocks 这是一个计数题,又把我卡自闭了...之前也碰到过类似的题目,这次居然还没有写出来,感觉自己还是太菜了,加油补题吧. 题目大意: 给你一个数字 \(n\),代表的 ...
- G - Queue HDU - 5493 线段树+二分
G - Queue HDU - 5493 题目大意:给你n个人的身高和这个人前面或者后面有多少个比他高的人,让你还原这个序列,按字典序输出. 题解: 首先按高度排序. 设每个人在其前面有k个人,设比这 ...