手撸web框架

web应用分析

什么是web应用?

Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件。典型的浏览器/服务器架构的产物。

针对于web应用的分析:

  1 不需要下载和更新,只要一个适用的浏览器

  2 不需要耗费用的户硬盘空间,或者很少

  3  跨平台使用

软件开发的架构:

  1 c/s 服务器和客户端

  2 b/c 服务器与浏览器(客户端)

  


 

浏览器和socket实现

 手撸简易版web框架

import socket

server = socket.socket() # 默认是tcp协议
server.bind(("127.0.0.1", 8080))
server.listen(4) #
while True:
conn, addr = server.accept()
data = conn.recv(1024)
conn.send(b'404')
conn.close()
# 浏览器不能识别

 http

按照http协议的改进版

import socket

server = socket.socket() # 默认是tcp协议
server.bind(("127.0.0.1", 8080))
server.listen(4) #
while True:
conn, addr = server.accept()
data = conn.recv(1024)
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
data = str(data, encoding="utf-8")
print(data)
path = data.split("\r\n")[0].split(" ")[1]
if path == "/login":
with open("login.html", 'rb')as f:
conn.send(f.read())
else:
conn.send(b'404')
conn.close()

 http协议请求数据格式

"""
GET / HTTP/1.1\r\n    # 请求首行
Host: 127.0.0.1:8080\r\n   # 请求头,都是key,value的键值对
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\n
Accept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n
\r\n

"""

 


 

wsgiref和浏览器实现

 基于第三方库wsgiref实现

不用自己去处理socket连接问题

from wsgiref.simple_server import make_server

def run(request, response):
print(request)
response("200 ok", [("name", "lynn")]) # 固定写法,后边裂变式一个个元组,会以响应头key,value键值对的形式的返回给客户端
return [b'hello world'] # 固定格式,必须是列表

server = make_server("127.0.0.1", 8080, run)
server.serve_forever()

进阶

from wsgiref.simple_server import make_server


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


def register():
with open("register.html", 'rb')as f:
data = f.read()
return data


url = [
("/login", login),
("/register", register),
]


def run(request, response):
print(request)
response("200 ok", [("name", "lynn")]) # 固定写法,后边裂变式一个个元组,会以响应头key,value键值对的形式的返回给客户端
path = request.get("PATH_INFO")
for u in url:
if path == u[0]:
return [u[1]()]

return [b'hello world'] # 固定格式,必须是列表


if __name__ == '__main__':
server = make_server("127.0.0.1", 8080, run)
server.serve_forever()

动态页面

页面代码虽然没有变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的

静态网页

随着html代码的生成,页面的内容和显示效果就基本上不会发生变化了——除非你修改页面代码

 

import time
from wsgiref.simple_server import make_server


def get_time():
    return time.strftime("%Y")

url = [
    ("/get_time", get_time)
]

def run(request, response):

    response("200 ok", [("name", "lynn")])  # 固定写法,后边裂变式一个个元组,会以响应头key,value键值对的形式的返回给客户端
    path = request.get("PATH_INFO")
    for u in url:
        if path == u[0]:
            return [u[1]().encode("utf-8")]
    return [b'hello world']  # 固定格式,必须是列表


if __name__ == '__main__':
    server = make_server("127.0.0.1", 8080, run)
    server.serve_forever()

终极版本分文件

urls.py

url = [
    ("/login", login),
    ("/register", register),
]

views.py

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


def register():
    with open("register.html", 'rb')as f:
        data = f.read()
    return data

 


 

jinja2实现页面渲染

什么是模板渲染?

后端数据直接加载到前端html页面直接使用

自己去做

urls.py

from views import *

url = [
    ("/login", login)
]

views.py 

def login():
    with open("login.html", 'r')as f:
       data =  f.read()
       return data.replace("@@name@@", "lynn")

主文件.py

from urls import *
from wsgiref.simple_server import make_server


def run(request, response):
    response("200 OK", [("name", "lynn")])
    path = request.get("PATH_INFO")
    for u in url:
        if u[0] == path:
            return [bytes(u[1](), encoding="utf-8")]
    return [b'404']


if __name__ == '__main__':
    server = make_server("127.0.0.1", 8080, run)
    server.serve_forever()

总结:

  麻烦不灵活,自己要去匹配,数据类型复杂后,处理起来很麻烦

用jinja2实现

views.py

from jinja2 import Template


def login():
    with open("login.html", 'r', encoding="utf-8")as f:
        data = f.read()
    tem_data = Template(data)
    return tem_data.render(user_dic={"name": "lynn", "password": 123}) # 固定用法,把字典渲染到前端html上

主文件.py

from urls import *
from wsgiref.simple_server import make_server

def run(request, response): response("200 OK", [("name", "lynn")]) path = request.get("PATH_INFO") func = None for u in url: if u[0] == path: func = u[1] break if func: res = func() else: res = '404' return [res.encode('utf-8')] # 所有的数据在最后再编码成bytes if __name__ == '__main__': server = make_server("127.0.0.1", 8080, run) server.serve_forever()

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<p>{{ user_dic.name }}</p> 
<p>{{ user_dic["password"] }}</p>
<p>{{ user_dic.get("name") }}</p>

</body>
</html>

 

 

posted @ 2019-12-02 12:59  tianzhh_lynn  阅读(389)  评论(0编辑  收藏  举报