python实现mini_web框架

11.1python实现mini_web框架

理解框架,路由,模版

1静态资源动态资源

静态资源,不需要经常改变,js,css,html,web服务器保存
动态资源,动态变化数据,需要根据情况/条件变化的数据
模版就是一个空的网页,需要从数据库查询对应资源进行填充

![](/Users/keith/Desktop/屏幕快照 2018-11-01 上午9.29.54.png)

web框架应用程序(View)是动态解析客户端请求,调用数据库(Module),填充到模版(Templete)
合起来称作MVT模式,这就是我们需要做的

WSGI协议

框架和服务器是不兼容的,为了实现兼容这个目标,所有服务器程序和框架都遵循WSGI协议
服务器的功能就是收发消息,创建套接字,而框架的功能上面写了

作为框架要满足两条:
1.需要是一个可调用的对象:函数,实例(具有call方法),类
2.要接受两个参数
3.可调用对象要能返回一个值,并且这个值要能可迭代

作为服务器要满足:
能调动框架

除了这两个还有一些功能介于两者之间

2.web开发和爬虫领域

web服务器:nginx(c,python,等天生高并发),gunicom(flask),apache(java较多)
web框架:flask,django
我们做web开发,主要就是做框架
做爬虫就是把自己伪装成浏览器,爬网页app数据,原理类似

3.实现一个简单web框架

还是借助上面那个图
浏览器和web服务器通过http协议通信,服务器和框架通信遵循wsgi协议,下面就定义一个简单的协议,实现服务器和框架的通信;
之前写的web服务器能实现静态资源的处理


怎么分别是动态还是静态资源:
动态 .html结尾
静态 其他(图片cssjs)
如果是动态资源请求交给框架处理:

#web.py
import Application
if path_info.endwith('.html'):
    #字典可以根据key拿到value,定义一个字典 储存用户请求信息
    env ={
        'PATH_INFO':path_info
    
    }
    status, headers, response_body = Application.app(env)
    #使用框架返回的数据,拼接响应报文
    response_line = 'HTTP/1.1 %s\r\n' %status
    response_header = ''
    #框架返回多个头,返回列表里元组
    for header in headers:
        response_header +='%s:%s\r\n' % header
    #所有拼接起来
    response_data = (response_line+ response_header +'\r\n'+response_body).encode('utf8')
    #send
    
    
    


#Application.py   
def app(env)
    #接收 取出用户的信息
    path_info = env['PATH_INFO']
    
    #状态,响应头,响应体
    return '200 OK',[('Server','PWS5.0')],'body'  
    

4.返回动态资源的函数

#Application.py
import time  
def gettime():
    return time.ctime() 
def app(env):
    #接收 取出用户的信息
    path_info = env['PATH_INFO']
    if path_info == '/gettime.html'
        return '200 OK',[('Server','PWS5.0')],gettime()
    
    #状态,响应头,响应体
    return '200 OK',[('Server','PWS5.0')],'body'  

5.模版概念template

#Application.py
import time  
def gettime():
    return time.ctime() 
    
def index()
    #当用户请求/index.html
    #1 读取模版文件
    with open('template/index.html') as file:
        html_data= file.read()
    #2 查询数据库
    data_from_mysql=
    #3 使用从数据库查找的数据替换模版变量
    html_data = html_data.replace('{%content%}',data_from_mysql)
    
    return html_data
    
def app(env):
    #接收 取出用户的信息
    path_info = env['PATH_INFO']
    if path_info == '/gettime.html'
        return '200 OK',[('Server','PWS5.0')],gettime()
    
    #状态,响应头,响应体
    return '200 OK',[('Server','PWS5.0')],'body'  

模版变量:需要将模版变量替换成需要的数据就形成完整的网页

6.django添加路由方式

当页面较多时候,使用if,else判断效率太低,引入路由概念,这个路由分配可以是字典,用户输入地址,分配函数(视图函数)

路由列表:把所有的请求路径和执行代码存到一个列表中
用字典还是用列表实现都行

#Application.py
#定义路由列表
roote_list=[
	('/gettime.html',get_time),
	('/center.html',center)
]

def app(env):
	path_info = env['PATH_INFO']
	#将用户请求路径和路由列表每一项一一比较,如果一致,就执行响应代码
	for path, func in route_list:
	    if pat_info == path:
	    	return '200 OK',[('Server','PWS5.0')],func()

这里的添加路由方式就是django框架添加路由的方式

7.Flask添加路由方式

装饰器工厂就是带参数装饰器
借助装饰器的形式把路径,视图函数添加到路由中

route_list = [

]

def route(path):
	#可以用path
	def warrpper(func):
		#可以用func,此时没有被装饰
		route_list.append((path, func))
		def inner():
			pass
		return inner
	return warrper

#这句话相当于warpper = route('/gettime.html') gettime = warpper(gettime)
@route('/gettime.html')
def gettime()
	pass

被装饰后,被装饰函数指向闭包内部函数,闭包外部函数参数指向被装饰函数,只要添加了装饰器,立马执行闭包之外的代码,所以立即添加到路由列表中,很快捷

8显示股票信息页面


def mysql():
	#提供资源
	conn = connect(host='localhost',port=3306,db='stockt_db',user='root',password='mysql')
	cur = conn.cursor()
	
	yield cur
	conn.commit()
	#关闭资源
	cur.close()
	conn.close()

借助上下文管理器,with,管理方法,
@contextmanager 装饰器简单管理

个人中心页面

连接多张表

import time
route_list = []
from contextlib import contextmanager
from pymysql import connect

def route(path):
    def warrper(func):
        route_list.append((path,func))
        print('----添加了一条路由')
        print(route_list)
        def inner():
            pass
        return inner
    return warrper

@contextmanager
def getmysql():
    conn = connect(host='localhost',port=3306,database ='stock_db',user='root',password='12345678')
    sur = conn.cursor()
    yield sur
    conn.commit()
    sur.close()
    conn.close()

@route('/time.html')
def gettime():
    return time.ctime()

@route('/index.html')
def getindex():
    with open('template/index.html') as f:
        content = f.read()
    with getmysql() as g:
        sql = 'select * from info;'
        g.execute(sql)
        data_from_mysql = ''
        for i in g.fetchall():
            line_str = """<tr>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td><input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="000007"></td>
                        </tr>""" % i
            data_from_mysql += line_str

    content = content.replace("{%content%}", data_from_mysql)


    return content

@route('/center.html')
def getindex():
    with open('template/center.html') as f:
        content = f.read()

    return content



def app(env):
    path_info = env['PATH_INFO']
    for path,func in route_list:
        if path_info == path:
            return '200 OK',[('Server','PWS')],func()



猜你喜欢

转载自blog.csdn.net/JessePinkmen/article/details/83625782