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">&lt;!&ndash;以get请求方式auth验证&ndash;&gt;-->
<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框架的更多相关文章

  1. 10款Web开发最佳的Python框架

    Python是跻身于当代IT世界最流行和代码最高效的编程语言之一.Python框架能帮助你快速启动Web应用. 1.CubicWeb CubicWeb的最重要的功能是其代码的可重用性,由一个个代码单元 ...

  2. 2018年要学习的10大Python Web框架

    通过为开发人员提供应用程序开发结构,框架使开发人员的生活更轻松.他们自动执行通用解决方案,缩短开发时间,并允许开发人员更多地关注应用程序逻辑而不是常规元素. 在本文中,我们分享了我们自己的前十大Pyt ...

  3. 转-基于NodeJS的14款Web框架

    基于NodeJS的14款Web框架 2014-10-16 23:28 作者: NodeJSNet 来源: 本站 浏览: 1,399 次阅读 我要评论暂无评论 字号: 大 中 小 摘要: 在几年的时间里 ...

  4. 【原】Go语言及Web框架Beego环境无脑搭建

    本文涉及软件均以截至到2013年10月12日的最新版本为准 1. 相关软件准备: 1) go1.2rc1.windows-386.msi,对应32位windows系统安装使用 下载地址: https: ...

  5. web框架django初探

    Web框架介绍 一般会分为两部分:服务器程序和应用程序.服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理.应用程序则负责具体的逻辑处理.为了方便应用程序的开发,就出 ...

  6. 第三篇 基于.net搭建热插拔式web框架(重造Controller)

    由于.net MVC 的controller 依赖于HttpContext,而我们在上一篇中的沙箱模式已经把一次http请求转换为反射调用,并且http上下文不支持跨域,所以我们要重造一个contro ...

  7. Python之Web框架Django

    Python之Web框架: Django 一. Django Django是一个卓越的新一代Web框架 Django的处理流程 1. 下载地址  Python 下载地址:https://www.pyt ...

  8. 第一个web框架tornado

    简介 tornado,是我学到的第一个web框架是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google ...

  9. web框架 之 Tornado

    初识 Tornado : tornado web server 是使用python编写出来的一个轻量级.高可伸缩性和非阻塞IO的Web服务器软件,其特点是采用epoll非阻塞IO,相应快速,可处理数千 ...

随机推荐

  1. Git初始化本地代码及提交到服务器

    2019独角兽企业重金招聘Python工程师标准>>> 1.先安装Git客户端 2.进入需要提交的文件夹目录 3.打开Git Bash,点击右键中的Git Bash 打开git命令窗 ...

  2. SQL语句学习(二)

    为一张表添加外键: 这里我们希望再建一张订单的表为t_order,包含order_id,customer_id和price: ) NOT NULL auto_increment PRIMARY KEY ...

  3. TreeMap分析(中)

    通过上篇文章,大家已经能够理解红黑树的基础数据结构,那么这篇文章就来分析下,在红黑树中插入一个结点后,内部数据结构发生了哪些变化. TreeMap插入某个结点的源码分析 /** * 插入节点,并平衡红 ...

  4. 一维滑动窗口(SlidingWindow)

    滑动窗口(Sliding Window)问题经常使用快慢指针(slow, fast pointer)[0, slow) 的区域为滑动窗口已经探索过的区域[slow, fast]的区域为滑动窗口正在探索 ...

  5. Java—线程池ThreadPoolExecutor详解

    引导 要求:线程资源必须通过线程池提供,不允许在应用自行显式创建线程: 说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题.如果不使用线程池,有可能造成系统 ...

  6. muduo网络库源码学习————无界队列和有界队列

    muduo库里实现了两个队列模板类:无界队列为BlockingQueue.h,有界队列为BoundedBlockingQueue.h,两个测试程序实现了生产者和消费者模型.(这里以无界队列为例,有界队 ...

  7. SpringBoot上传文件大小限制

    SpringBoot默认上传文件大小不能超过1MB,超过之后会报以下异常: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSize ...

  8. 挑战程序竞赛 反转开关 poj3276

    这个我其实也没有看太懂它的证明过程. 1.若某一个位置被翻转了n次,则其实际上被翻转了n%2次. 2.分析易知翻转的顺序并不影响最终结果. 3.现在我们着眼于第1个位置,可知若要将第1个位置进行翻转只 ...

  9. rsync 服务及部署

    1 rsync简介 1.1 什么是rsync rsync: - a fast, versatile, remote (and local) file-copying toolrsync:是一种快速,多 ...

  10. spring表达式语言

    使用文本表达式 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http: ...