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,相应快速,可处理数千 ...
随机推荐
- tagbar 调到函数定义再跳回
首先要在源码文件夹下执行 ctags -R * 生成tags文件 齐次要安装 YouCompleteMe ctrl + ] 跳到函数定义 Ctrl-o 和 Ctrl-I 跳回.我试验的只有 Ctrl- ...
- 基于Apache+Tomcat实现负载均衡
1.基于Apache和tomcat实现负载均衡 准备三个虚拟机一个安装Apache两个安装Tomcat 关闭防火墙 systemctl stop firewalld Iptabled -F Seten ...
- 还在写CURD?试试这款基于mybatis-plus的springboot代码生成器
目录 ⚡Introduction ✔️Release Features Quick Start Examples 1.Controller模板代码示例 2.Service模板代码示例 3.Servic ...
- React全家桶+AntD 共享单车后台管理系统开发
第1章 课程导学对课程整体进行介绍,并且说明学习的必要性.第2章 React基础知识React基础知识以及生命周期的介绍,并使用React官方脚手架初始化基础项目,同时介绍了新一代打包工具Yarn.第 ...
- Android Studio SVN配置忽略文件
1.用Android Studio创建一个项目,会在根目录和Module目录下自动生成.gitignore文件,貌似是Git的配置文件,和SVN没有关系. 2.打开Setting-Version Co ...
- 一句话总结JS构造函数、原型和实例的关系
"每个构造函数都有一个原型对象, 原型对象都包含一个指向构造函数的指针, 实例都包含一个指向原型对象的内部指针." --此段话摘自<JavaScript高级程序设计>. ...
- 数学--数论--HDU 1098 Ignatius's puzzle (费马小定理+打表)
Ignatius's puzzle Problem Description Ignatius is poor at math,he falls across a puzzle problem,so h ...
- Jenkins 构建 Jmeter 项目之源代码管理(SVN)
1.查看项目创建中是否又 svn 插件,没有的话下载插件 subversion 2.配置 svn 源代码管理,如下图(testcases 目录下包含 build.xml 和脚本文件) 3.查看 Jen ...
- ssm整合后打印日志查看执行sql语句
mybatis.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configura ...
- leetcode485——最大连续1的个数(easy)
一.题目描述 给定一个二进制数组, 计算其中最大连续1的个数. 示例 1: 输入: [1,1,0,1,1,1] 输出: 3 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3. 注意 ...