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,相应快速,可处理数千 ...
随机推荐
- QT 的 parent 该如何理解
对话框是GUI程序和用户进行简短交互的顶层窗口,所谓顶层窗口即始终在主窗口之上显示.QDialog是Qt所有类型的对话框窗口的基类,它继承于QWidget,是一种容器类型组件. QWidget是所有窗 ...
- [Batch脚本] if else 的格式
必须写成一行 ) else (,否则报错. if %abc%=="yes" ( ... ) else ( ... )
- Taro 2.2 全面插件化,支持拓展和定制个性化功能
自 2.2 开始,Taro 引入了插件化机制,允许开发者通过编写插件的方式来为 Taro 拓展更多功能或者为自身业务定制个性化功能,欢迎大家进行尝试,共同讨论~ 当前版本 2.2.1 官方插件 Tar ...
- Vue3.0新版API之composition-api入坑指南
关于VUE3.0 由于vue3.0语法跟vue2.x的语法几乎是完全兼容的,本文主要介绍了如何使用composition-api,主要分以下几个方面来讲 使用vite体验vue3.0 composit ...
- opencv-0-项目启程
opencv-0-项目启程 opencvC++QT 开始 无数次说要开始 opencv 的系列, 但是都由于各种原因没有坚持下去, 这次我做最后一次尝试, 也做最后一次坚持, 如果不做下去, 我就再也 ...
- 标准库hashlib模块
hashlib模块用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512, MD5 算法(都是基于hash的算法, ...
- Golang项目部署
文章来源:https://goframe.org/deploymen... 一.独立部署 使用GF开发的应用程序可以独立地部署到服务器上,设置为后台守护进程运行即可.这种模式常用在简单的API服务项目 ...
- OSChina 清明节乱弹 ——准备好纸巾了看乱弹
2019独角兽企业重金招聘Python工程师标准>>> Osc乱弹歌单(2017)请戳(这里) [今日歌曲] @亚麻仔 :分享 范忆堂 的歌曲<酡颜 (夏热版)> 同一个 ...
- redhat7.3 dns服务器配置
1.基本配置 systemctl stop firewalld.service systemctl disable firewalld.service setenforce 0 nmcli conne ...
- 从实践出发:微服务布道师告诉你Spring Cloud与Boot他如何选择
背景 随着公司业务量的飞速发展,平台面临的挑战已经远远大于业务,需求量不断增加,技术人员数量增加,面临的复杂度也大大增加.在这个背景下,平台的技术架构也完成了从传统的单体应用到微服务化的演进. 系统架 ...