mini-web框架

1.web框架与web服务器的关系

web服务器主要是接收用户的http请求,根据用户的请求返回不同的资源数据,静态web服务器返回的是静态数据,想要web服务器返回动态资源该怎么处理?
使用web框架专门负责处理用户的动态资源请求,web框架其实就是一个为web服务器提供服务的应用程序,简称web框架
web浏览器《---------http协议------》web服务器《-------.html动态资源请求(WSGI)协议------》web框架应用程《---------------》模板(静态html网页,但没有数据)
web服务器《----------静态资源请求---------------》静态资源
web框架应用程序《------动态数据索引-------------》数据库

  1. 说明:

    1. web服务器接收浏览器发起的请求,解析请求报文,若是动态资源请求,找web框架来处理
    2. web框架负责处理浏览器动态资源请求,把处理的结果发送给web服务器
    3. web服务器把响应结果封装成响应报文发送浏览器
  2. 静态资源:

    1. 不需要经常变化的资源,这种资源web服务器可以提前准备好,如:js/css/jpg
  3. 动态资源:

    1. 和静态资源相反,这种资源会经常变化,如:天猫信息,这种资源,web服务器无法提前准备,需要web框架来帮助web服务器进行准备,web服务器可以把.html的资源请求认为是动态资源请求,交由web框架进行处理
  4. WSGI协议:

    1. 是web服务器和web框架之间进行协同工作的一个规定,WSGI协议规定web服务器把动态资源请求的请求信息传给web框架处理,web框架把处理好的结果返回给web服务器。
  5. web框架是专门为web服务器处理动态资源请求的一个应用程序

  6. web框架和web服务器的关系是web框架专门服务于web服务器,给web服务器提供处理动态资源请求的服务

2.web框架开发-获取处理结果

  1. web框架职责:接收web服务器的动态资源请求,给web服务器提供处理动态资源请求的服务
  2. 动态资源判断:
    1. 根据请求资源路径的后缀名判断:
      1. 若请求资源路径的后缀名是.html则是动态资源请求,让web框架程序进行处理
      2. 反之是静态资源请求,让web服务器处理
#服务器:
 #判断是否是动态资源请求,以后把后缀是.html的请求任务认为是动态资源请求
        if response_html.endswith('.html'):
            '''动态资源请求'''
            #动态资源请求找web框架进行处理,需要请求参数给web框架
            #准备给web框架的参数信息,都要放到字典里  env协议规定的请求环境
            env={
                'request_path':response_html,
                #传入请求头信息 额外的参数可在字典字典添加
            }
            #使用框架处理动态的资源请求
            # 1.web框架需要把处理结果 返回给web服务器
            #2.web服务器负责 将返回的结果 封装成响应报文 发送给浏览器
            #状态信息 响应头信息 响应体信息
            status,headers,response_body=framework.handle_request(env)
            print(status,headers,response_body)
            #响应行
            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('utf-8')
            #发送响应报文给浏览器
            new_socket.send(response_data)
            #关闭
            new_socket.close()

        else:
            '''静态资源请求'''
            #判断请求页是否存在 返回静态资源
            try:
            	...
#web框架:
import time
#获取首页数据
def index():
    #状态信息
    status='200 OK'
    #响应头信息 可以是字典/元组
    response_header=[("Server","PWS/1.1")]
    #1.打开指定的模板文件,读取模板文件中的数据
    with open('./wenjian/template/ind.html','r')as f:
        f_data=f.read()
    #2.查询数据库,模板里面的模板变量{%data%} 替换成从数据库查询到的数据
    #响应体 web处理后的数据
    #3.模拟查询到的数据
    data=time.ctime()#获取当前时间
    #4.模板数据替换
    response_body=f_data.replace('{%data%}',data)
    #返回的是一个元组
    return status,response_header,response_body
#处理没有动态资源
def not_found():
    # 状态信息
    status = '404 Not Found'
    # 响应头信息 可以是字典/元组
    response_header = [("Server", "PWS/1.1")]
    # 响应体 web处理后的数据
    data = 'Not Found'
    # 返回的是一个元组
    return status, response_header, data
#处理动态资源请求
def handle_request(env):
    #获取动态的请求资源路径
    request_path=env['request_path']
    print('动态资源请求的地址:',request_path)
    #判断请求的资源路径,选择指定的函数处理 对应的动态资源请求
    if request_path=='/ind.html':
        #首页数据
        result=index()
        #把处理后的结果返回给web服务器,让服务器拼接响应报文时使用
        return result
    else:
        #没有动态资源数据 返回404状态
        result=not_found()
        return result

3.路由列表开发

如果框架处理页面请求过多,普通分支无法忍受?
什么是路由?
路由是请求的URL到处理函数的映射,也就是说提前把请求的URL和处理函数关联好
路由列表:
这么多的路由如何管理,可以使用一个路由列表进行管理,通过路由列表保存每一个路由

请求路径处理函数
/log.htmllog函数
/index.htmlindex函数
/result.htmlresult函数
#web框架
#路由列表 列表里的每一条记录都是一个路由
route_list=[
    ('/ind.html',index),
    ('/rest.html',rest)
]
#处理动态资源请求
def handle_request(env):
    #获取动态的请求资源路径
    request_path=env['request_path']
    print('动态资源请求的地址:',request_path)
    #遍历路由列表,匹配请求的url
    for path,func in route_list:
        print(path,func)
        if request_path==path:
            #找到了指定路由,执行相应的处理函数
            result=func()
            return result
    else:
        # 没有动态资源数据 返回404状态
        result = not_found()
        return result

4.装饰器方式添加路由

通过装饰器的完成路由的自动添加,使用装饰器对处理函数进行装饰的时候,需要知道装饰的函数和请求路径进行相关联,也就是说装饰器需要接受一个url参数,因为定义的装饰器是一个有参数的装饰器

#web框架
import time
#路由列表 列表里的每一条记录都是一个路由
#Django路由列表
route_list=[
    # ('/ind.html',index),
    # ('/rest.html',rest)
]
#定义一个有参数的装饰器
def route(path):
    #装饰器 当执行装饰器的时候就需要将路由添加到路由列表中
    def decorator(func):
        #装饰函数的时候添加一次即可
        route_list.append((path,func))
        def inner():
            result=func()
            return result
    return decorator
#Flask使用
@route('/ind.html')
#获取首页数据
def index():
    #状态信息
    status='200 OK'
    #响应头信息 可以是字典/元组
    response_header=[("Server","PWS/1.1")]
    #1.打开指定的模板文件,读取模板文件中的数据
    with open('./wenjian/template/ind.html','r')as f:
        f_data=f.read()
    #2.查询数据库,模板里面的模板变量{%data%} 替换成从数据库查询到的数据
    #响应体 web处理后的数据
    #3.模拟查询到的数据
    data=time.ctime()#获取当前时间
    #4.模板数据替换
    response_body=f_data.replace('{%data%}',data)
    #返回的是一个元组
    return status,response_header,response_body
#rest页面
@route('/rest.html')
#获取首页数据
def rest():
    #状态信息
    status='200 OK'
    #响应头信息 可以是字典/元组
    response_header=[("Server","PWS/1.1")]
    #1.打开指定的模板文件,读取模板文件中的数据
    with open('./wenjian/template/rest.html','r')as f:
        f_data=f.read()
    #2.查询数据库,模板里面的模板变量{%data%} 替换成从数据库查询到的数据
    #响应体 web处理后的数据
    #3.模拟查询到的数据
    data='你好,这里是rest也数据'#获取当前时间
    #4.模板数据替换
    response_body=f_data.replace('{%data%}',data)
    #返回的是一个元组
    return status,response_header,response_body
#处理没有动态资源
def not_found():
    # 状态信息
    status = '404 Not Found'
    # 响应头信息 可以是字典/元组
    response_header = [("Server", "PWS/1.1")]
    # 响应体 web处理后的数据
    data = 'Not Found'
    # 返回的是一个元组
    return status, response_header, data

#处理动态资源请求
def handle_request(env):
    #获取动态的请求资源路径
    request_path=env['request_path']
    print('动态资源请求的地址:',request_path)
    #遍历路由列表,匹配请求的url
    for path,func in route_list:
        print(path,func)
        if request_path==path:
            #找到了指定路由,执行相应的处理函数
            result=func()
            return result
    else:
        # 没有动态资源数据 返回404状态
        result = not_found()
        return result

5.数据库连接

#web框架
    #2.查询数据库,模板里面的模板变量{%data%} 替换成从数据库查询到的数据
    #创建连接对象
    conn=pymysql.connect(host="localhost",
                         port=3306,
                         user="root",
                         password="123456",
                         database="jd",
                         charset="utf8"
                         )
    #获取游标
    cursor=conn.cursor()
    #执行sql语句
    sql="select * from goods;"
    cursor.execute(sql)
    #获取查询结果
    result=cursor.fetchall()
    #关闭游标
    cursor.close()
    #关闭连接对象
    conn.close()
    #遍历每一条数据,完成数据的封装
    data=""
    for i in result:
        data+='<h3>%s-%s-%s-%s</h3>'%i

	 #响应体 web处理后的数据
    #3.模拟查询到的数据
    # data=time.ctime()#获取当前时间
    #4.模板数据替换
    response_body=f_data.replace('{%data%}',data)
    #返回的是一个元组
    return status,response_header,response_body
    。。。

6.个人数据接口开发

数据接口返回的是一个json格式数据,可以供他人使用

#个人数据中心接口
@route('/center_data.html')
def center_data():
    #从数据库查询数据,将查询的数据转换为json格式
    #创键连接对象
    conn=pymysql.connect(
        host='localhost',
        user='root',
        password='123456',
        database='jd',
        charset='utf8'
    )
    #获取游标
    cursor=conn.cursor()
    #执行sql
    sql="select cart.goodsprice,goods.`name` from  cart inner join goods on cart.goodsid=goods.id;"
    cursor.execute(sql)
    #获取查询结果
    result=cursor.fetchall()
    # print(result)
    #关闭游标
    cursor.close()
    #关闭连接
    conn.close()
    #将查询结果转换为json数据格式
    #1.将元组转换为列表字典
    center_data_list=[{'price':str(row[0]),
                      'name':row[1]
                      }for row in result]
    #2.将列表转转为json字符串数据 需要导包 json ensure_ascii=False表示在控制台显示中文
    json_str=json.dumps(center_data_list,ensure_ascii=False)
    # print(json_str)
    # 状态信息
    status = '200 OK'
    # 响应头信息 可以是字典/元组
    response_header = [("Server", "PWS/1.1"),
                       # 指定编码格式。因为没有模板文件,可以通过响应头指定编码格式
                       ("Content-Type","text/html;charset=utf-8")]
    return status,response_header,json_str

7.ajax请求数据渲染个人中心页面

<script>
        $(document).ready(function(){
        //    发送ajax请求,获取个人中心数据
            $.get("/center_data.html",function (data){
            //    ajax成功回调函数
            //    获取table标签 css样式选择
                var $table=$("table");
            //    如果指定了返回数据的解析方法为json,则data就是一个js对象
                console.log(data)
                for(var i=0;i<data.length;i++){
                //    根据下标取每一条数据
                    var oCenterData=data[i];
                    var oTr='<tr>'+
                        '<td>'+oCenterData.price+'</td>'+
                        '<td>'+oCenterData.Lname+'</td>'+'</tr>'
                //    给table标添加一行tr标签
                    $table.append(oTr)
                }
            },"json");
        });
</script>
。。。
<table>
    <tr>
        <td>你好,这里是ajax请求</td>
        <td>{%data%}</td>
    </tr>
</table>

#框架端
#rest页面
@route('/rest.html')
#获取首页数据
def rest():
    #状态信息
    status='200 OK'
    #响应头信息 可以是字典/元组
    response_header=[("Server","PWS/1.1")]
    #1.打开指定的模板文件,读取模板文件中的数据
    with open('./wenjian/template/center_data.html','r',encoding='utf-8')as f:
        f_data=f.read()
    #2.查询数据库,模板里面的模板变量{%data%} 替换成从数据库查询到的数据
    #响应体 web处理后的数据
    #3.模拟查询到的数据
    data='你好,这里是rest也数据'#获取当前时间
    #4.模板数据替换
    response_body=f_data.replace('{%data%}','')
    # response_body=f_data
    #返回的是一个元组
    return status,response_header,response_body
    
#个人数据中心接口
@route('/center_data.html')
def center_data():
    #从数据库查询数据,将查询的数据转换为json格式
    #创键连接对象
    conn=pymysql.connect(
        host='localhost',
        user='root',
        password='123456',
        database='jd',
        charset='utf8'
    )
    #获取游标
    cursor=conn.cursor()
    #执行sql
    sql="select cart.goodsprice,goods.`name` from  cart inner join goods on cart.goodsid=goods.id;"
    cursor.execute(sql)
    #获取查询结果
    result=cursor.fetchall()
    # print(result)
    #关闭游标
    cursor.close()
    #关闭连接
    conn.close()
    #将查询结果转换为json数据格式
    #1.将元组转换为列表字典
    center_data_list=[{'price':str(row[0]),
                      'Lname':row[1]
                      }for row in result]
    #2.将列表转转为json字符串数据 需要导包 json ensure_ascii=False表示在控制台显示中文
    json_str=json.dumps(center_data_list,ensure_ascii=False)
    # print(json_str)
    # 状态信息
    status = '200 OK'
    # 响应头信息 可以是字典/元组
    response_header = [("Server", "PWS/1.1"),
                       # 指定编码格式。因为没有模板文件,可以通过响应头指定编码格式
                       ("Content-Type","text/html/json;charset=utf-8")]
    return status,response_header,json_str

8.logging日志

  1. logging初识
    记录程序运行时产生的日志信息
  2. 记录程序日志的目的:
    1. 可以很方便的了解程序的运行情况
    2. 可以分析用户的操作行为,喜好等信息
    3. 方便开发人眼检查bug
  3. logging日志级别
    1. 日志等级可以分为5个,由低到高:
      1. DEBUG
      2. INFO
      3. WARNING
      4. ERROR
      5. CRITICAL
    2. 日志等级说明:
      1. DEUG:调试时用
      2. INFO:程序正常运行时使用
      3. WARNING:程序未正常运行时使用,但并不是错误,如:用户登录密码错误
      4. ERRRO:程序出错误时使用,如:IO操作失败
      5. CRITICAL:特别严重的问题,导致程序不能再继续运行使用,如:磁盘空间为空。一般很少使用
      6. 默认的是WARNING等级,当在WARNING或WARNING之上等级的才记录日志信息
  4. logging日志的使用
    1. 记录方式有两种:
      1. 输出到控制台
      2. 保存到日志文件
import logging
logging.debug('这是一个debug级别的日志')
logging.info('这是一个info级别的日志')
logging.warning('这是一个warning级别的日志')
logging.error('这是一个error级别的日志')
logging.critical('这是一个critical级别的日志')

输出:
WARNING:root:这是一个warning级别的日志
ERROR:root:这是一个error级别的日志
CRITICAL:root:这是一个critical级别的日志
  1. 说明:日志信息只显示大于等于WARNNING级别的日志,这说明默认的日志级别是WARNING
  2. 日志等级和输出格式
#设置日志等级与格式 过去当前时间 输出文件名 第几行
logging.basicConfig(level=logging.DEBUG,format='%(asctime)s-%(filename)s[lineno:%(lineno)d]')

#日志输出到控制台
""""""
#设置日志等级与格式 过去当前时间 输出文件名 第几行 级别 日志信息
logging.basicConfig(level=logging.DEBUG,format='%(asctime)s-%(filename)s[lineno:%(lineno)d]-%(levelname)s-%(message)s')

#日志输出到控制台
""""""
import logging
logging.debug('这是一个debug级别的日志')
logging.info('这是一个info级别的日志')
logging.warning('这是一个warning级别的日志')# WARNING:root:这是一个warning级别的日志
logging.error('这是一个error级别的日志')# ERROR:root:这是一个error级别的日志
logging.critical('这是一个critical级别的日志')# CRITICAL:root:这是一个critical级别的日志

输出:

2021-09-23 20:45:29,571-test.py[lineno:3415]-DEBUG-这是一个debug级别的日志
2021-09-23 20:45:29,572-test.py[lineno:3416]-INFO-这是一个info级别的日志
2021-09-23 20:45:29,572-test.py[lineno:3417]-WARNING-这是一个warning级别的日志
2021-09-23 20:45:29,572-test.py[lineno:3418]-ERROR-这是一个error级别的日志
2021-09-23 20:45:29,572-test.py[lineno:3419]-CRITICAL-这是一个critical级别的日志



  • 此后如竟没有炬火,我便是唯一的光
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值