web框架介绍

2.wsgiref模块

    最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。这个接口就是WSGI:Web Server Gateway Interface。而wsgiref模块就是python基于wsgi协议开发的服务模块。

示例学习

from wsgiref.simple_server import make_server
"""make_server已经封装了socket,所以不需要额外调用!"""
# import socket
import socket # 重用端口需要

"""
wsgiref 按着FTTP请求协议解析数据
        按着HTTP相应协议封装数据

我们就可以专注于web业务开发
python下的web服务器接口协议:WSGI(Web Server Gateway Interface)
wsgiref是为python实现WSGI的一个模块!
"""

def application(environ, start_response):
    """自定义的回调函数 两个形参接受的参数为
    按着http协议解析的数据字典:environ(存着所有的请求数据,包括头和体,键值对的方式!)
    按着http协议组装数据的函数:stare_response
    """
    # print(environ)
    # print(type(environ))

    """start_response函数进行响应组装,包括响应首行(状态码等,首行必须有),响应头(可无)(可以忽略里面的\r\n这些格式)"""
    start_response('200 OK',  [('Content-Type', 'text/html')])
    """在这里我遇到一个编码出错的问题,原因是我用的win10系统,主机名用的是汉语,
    win默认的编码方式是gbk。在这里十分感谢老男孩路飞学城的alex和刘耀导师帮我指导并解决了这个问题"""


    # 得到当前的请求路径
    path = environ.get('PATH_INFO')
    print("当前的路径:" ,path)

    if path == "/login":
        with open('login.html', 'r', encoding='utf-8') as f:
            data = f.read()
    elif path == '/index':
        with open('index.html', 'r', encoding='utf-8') as f:
            data = f.read()
    else:
        data = '<h1>--404 Not find!--</h1>'

    """WSGI要求的返回值必须为一个数组"""
    return [data.encode('utf8')]


if __name__ == "__main__":
    """封装了socket"""
    httped = make_server("", 8088, application)

    """重用端口,(这里是我自己领悟的!老师没有讲)"""
    httped.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

    """等待用户连接 conn,addr=socket.accept()"""
    httped.serve_forever()

简化版

from wsgiref.simple_server import make_server
import socket # 重用端口需要

def application(environ, start_response):
    start_response('200 OK',  [('Content-Type', 'text/html')])
    path = environ.get('PATH_INFO')

    if path == "/login":
        with open('login.html', 'r', encoding='utf-8') as f:
            data = f.read()
    else:
        data = '<h1>--404 Not find!--</h1>'

    return [data.encode('utf8')]

if __name__ == "__main__":

    httped = make_server("", 8088, application)
    httped.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    httped.serve_forever()

3.自己DIV一个web框架

简单版

from wsgiref.simple_server import make_server
import socket # 重用端口需要

# 方案二:
def login(environ):
    with open('../login.html', 'rb') as f:
        data = f.read()
    return data

def index(environ):
    with open('../index.html', 'rb') as f:
        data = f.read()
    return data

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    path = environ.get('PATH_INFO')

    read_dic = {
        '/login':login,
        '/index':index,
    }

    try:
        return [read_dic[path](environ)]
    except:
        return [b'404']


if __name__ == "__main__":

    httped = make_server("", 8088, application)
    httped.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    httped.serve_forever()

html文件代码

略!

加入数据库版

目录结构

main.py


from wsgiref.simple_server import make_server


def application(environ, start_response):

    start_response('200 OK', [('Content-Type', 'text/html'),("Charset","utf8")])

    path = environ.get("PATH_INFO")
    print("PATH",environ.get("PATH_INFO"))

    from urls import url_patterns

    func=None
    for item in url_patterns:
        if path==item[0]:
            func=item[1]
            break

    if func:
        return [func(environ)]

    else:
        return [b'404!']


httpd = make_server('', 9988, application)

# 开始监听HTTP请求:
httpd.serve_forever()

urls.py



from views import *

url_patterns=[

    ("/login",login),  #视图函数
    ("/reg",reg),
    ("/index",index),
    ("/favicon.ico",fav),
    ("/timer",timer),
    ("/auth",auth),


]

views.py


def login(environ):

    with open("templates/login.html","rb") as f:
             data=f.read()
    return data

from urllib.parse import parse_qs

def index(environ):

     with open("templates/index.html","rb") as f:
        data=f.read()
     return data

def fav(environ):

     with open("templates/favicon.ico","rb") as f:
        data=f.read()
     return data

def reg(environ):

    with open("templates/reg.html","rb") as f:
        data=f.read()
    return data

def timer(environ):

    import datetime
    now = datetime.datetime.now().strftime('%y-%m-%d %X')
    return now.encode("utf8")


def auth(request):

    # 取出用户名和密码的逻辑
    try:
        request_body_size = int(request.get('CONTENT_LENGTH', 0)) #如果没有对应的字典值就返回0
    except (ValueError):
        request_body_size = 0

    request_body = request['wsgi.input'].read(request_body_size)
    data = parse_qs(request_body)

    user=data.get(b"user")[0].decode("utf8")
    pwd=data.get(b"pwd")[0].decode("utf8")


    #连接数据库
    import pymysql
    conn = pymysql.connect(host='127.0.0.1',port= 3306,user = 'root',passwd='abc123',db='web_yuan') # db:库名
    #创建游标
    cur = conn.cursor()
    SQL="select * from userinfo WHERE NAME ='%s' AND PASSWORD ='%s'"%(user,pwd)
    cur.execute(SQL)

    if cur.fetchone():

            f=open("templates/backend.html","rb")
            data=f.read()
            data=data.decode("utf8")
            return data.encode("utf8")
    else:
         return b"user or pwd is wrong"


models.py ---单独执行,用于生成数据


# 生成用户表
"""准备数据库
create database web_yuan;
"""
import pymysql
conn = pymysql.connect(host='127.0.0.1',port=3306,user = 'root',passwd='abc123',db='web_yuan')
cur = conn.cursor()

sql = '''
create table userinfo(
    id int primary key,
    name varchar(32),
    password varchar(32)
)

'''

cur.execute(sql)
conn.commit()
cur.close()
conn.close()

"""数据库中操作
insert userinfo values(1,'yuan','123');
"""

html代码

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>


<h4>welcome to luffyCity!</h4>

</body>
</html>

reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h4>注册页面</h4>

</body>
</html>

backend.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h3>Index</h3>

</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h4>登录页面</h4>

<form action="http://127.0.0.1:9988/auth" method="post">
    用户名<input type="text" name="user">
    密码<input type="password" name="pwd">
    <input type="submit">
</form>

</body>
</html>



总结

  • 0.main.py:启动文件,封装了socket
  • 1.urls.py:路径与视图函数的映射关系 ---url控制器
  • 2.views.py:视图函数部分,固定有一个形参-environ(包含所有的请求数据)---视图函数
  • 3.timplates文件夹:存放html文件 ---模板
  • 4.models:在项目启动前,在数据库中创建表结构 ----与数据库相关
posted @ 2018-06-24 22:39  哈哈大圣  阅读(256)  评论(0编辑  收藏  举报