一 web框架
Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法。web框架已经实现了很多功能,开发人员使用框架提供的方法并且完成自己的业务逻辑,就能快速开发web应用了。浏览器和服务器的是基于HTTP协议进行通信的。也可以说web框架就是在以上十几行代码基础张扩展出来的,有很多简单方便使用的方法,大大提高了开发的效率。
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 def mya(environ, start_response): print(environ) start_response('200 OK', [('Content-Type', 'text/html')]) if environ.get('PATH_INFO') == '/index': with open('index.html','rb') as f: data=f.read() elif environ.get('PATH_INFO') == '/login': with open('login.html', 'rb') as f: data = f.read() else: data=b'<h1>Hello, web!</h1>' return [data] if __name__ == '__main__': myserver = make_server('', 8011, mya) print('监听8010') myserver.serve_forever()
二、手撸一个Web框架
启动文件
from wsgiref.simple_server import make_server #wsgiref把socket进行了一个封装,我们就不需要在进行socket了 import urls from views import * # my_server()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数: # environ:一个包含所有HTTP请求信息的dict对象(是一个字典的形式) # start_response:一个发送HTTP响应的函数。 def my_server(environ, start_response): print(environ) print(environ['PATH_INFO']) # 调用start_response()函数就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。 # start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP,Header,每个Header用一个包含两个str的tuple表示。 # 通常情况下,都应该把Content - Type头发送给浏览器。其他很多常用的HTTPHeader也应该发送。 start_response('200 OK', [('Content-Type', 'text/html')]) func=None for url in urls.urls: if url[0]==environ['PATH_INFO']: #拿到url中ip和端口中的请求地址 func=url[1] #拿到我们分装好的html函数的内存地址,加括号就可以调用,然后取读HTML中的内容,返回给浏览器 break if func: response=func(environ) else: response= error(environ) return [response,] #然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。 if __name__ == '__main__': my=make_server('127.0.0.1',8001,my_server) #创建一个服务器,IP地址为127.0.0.1,端口是8000,处理函数是my_server: my.serve_forever() #开始监听HTTP请求
路由配置
import views urls=[ ('/index',views.index), ('/time',views.time), ('/user_list',views.user_list), ('/favicon.ico',views.favicon), ]
视图函数
import pymysql from jinja2 import Template # 1、index和time就是我们封装好的两个从文件夹中读取HTML文件的函数 def index(response): with open('templates/index.html','r',encoding='utf-8') as f: data=f.read() return data.encode('utf-8') def time(response): import datetime now=datetime.datetime.now().strftime('%Y-%m-%d %X') with open('templates/two.html','r',encoding='utf-8') as f: data=f.read() data=data.replace('@@time@@',now) return data.encode('utf-8') # 2、url_list是我们从数据库中读取数据的一个函数 def user_list(response): # 连接数据库拿数据 # 拿到一个数据库连接 conn=pymysql.connect(host='127.0.0.1',port=3306,user='root',database='test',password='egon123') # 拿到一个游标对象 cursor=conn.cursor(cursor=pymysql.cursors.DictCursor) # 执行sql cursor.execute('select * from user') # 把数据拿出来 user_list=cursor.fetchall() print(user_list) with open('templates/user_list.html','r',encoding='utf-8')as f: data=f.read() # 生成一个模板对象,需要传字符串 template=Template(data) # 相当于在执行data.replace(),返回替换完成的字符串 data=template.render(user_list=user_list) return data.encode('utf-8') # 3、当我们在浏览器中输入的ip和端口后面的不是urls列表中显示的请求地址,就是显示404 def error(request): return '404'.encode('utf-8') # 4、favicon封装的是一个图标的文件,响应到浏览器显示在网页的是一个页面图标 def favicon(request): with open('favicon.ico','rb') as f: data=f.read() return data
HTML模板templates
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <img src="https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=775f519ac08065386fe7ac41f6b4ca21/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg">' </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> @@time@@ </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户列表</title> </head> <body> <table border="1"> <thead> <tr> <th>id</th> <th>用户名</th> <th>密码</th> </tr> </thead> <tbody> {% for user in user_list%} <tr> <td>{{user.id}}</td> <td>{{user.name}}</td> <td>{{user.password}}</td> </tr> {%endfor%} </tbody> </table> </body> </html>