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- ...
- 二进制安装MySQL及破解密码
二进制安装MySQL及破解密码 1.确保系统中有依赖的libaio 软件,如果没有: yum -y install libaio 2.解压二进制MySQL软件包 tar xf mysql-5.7.24 ...
- var、let、const
var.let.const之间的区别和使用 1.var声明变量可以重复声明,而let不可以重复声明 let a = 1; let a = 2; var b = 3; var b = 4; a // I ...
- Python内置函数enumerate()
enumerate()是Python的内置函数. help(enumerate) Help on class enumerate in module builtins: class enumerate ...
- STL--priority_queue--自定义数据类型
STL中priority_queue的声明模板有3个参数priority_queue<Type,Container,Functional>. 当使用的数据类型Type为自定义数据类型时有以 ...
- .NET Core+WebApi+EF访问数据新增用户数据
新建一个.NET Core项目,我使用的IDE是VS2019 依次创建三个Core类库:第一个命名api.Model,第二个api.Common,第三个api.Bo 解释一下这个三类库的作用: 第一个 ...
- codeforces 1287A -Angry Students(模拟)
It's a walking tour day in SIS.Winter, so t groups of students are visiting Torzhok. Streets of Torz ...
- ACM-ICPC 2019 山东省省赛D Game on a Graph
Game on a Graph Time Limit: 1 Second Memory Limit: 65536 KB There are people playing a game on a con ...
- P1458 顺序的分数 Ordered Fractions(有技巧的枚举)+C++类封装=精简代码
题目描述 输入一个自然数N,对于一个最简分数a/b(分子和分母互质的分数),满足1<=b<=N,0<=a/b<=1,请找出所有满足条件的分数. 这有一个例子,当N=5时,所有解 ...
- HTML(表格标签)
<table> 标签 表格由 <table> 标签来定义.每个表格均有若干行(由 <tr> 标签定义),每行被分割为若干单元格(由 <td> 标签定义) ...