Python从零开始编写轻量级Web框架(1)

编写一个轻量级的Web应用框架

最近阅读了Flask的源码,弄懂了原理之后就想尝试来实现自己的一个Web框架。

因为大部分的实现思路都参照Flask0.1版本,也就是最初版本的思路。所用的基本库是werkzeug

框架的完整代码都放在了Github上,之后会继续更新:https://github.com/jyz0309/WebFrame
求star,球球了T_T

总体思想:

按照flask的最基本功能的实现思想,首先建立url_map的字典进行url和视图函数的对应关系。

首先,当一个请求进来的时候,优先进入的是App类的__call__()回调函数,然后进入到wsgi_app函数中,在这个函数中进行请求的分发处理以及响应的返回。

具体的实现在代码中的注释。

以下是代码:

import os
from werkzeug.wrappers import BaseRequest, BaseResponse
from werkzeug.exceptions import HTTPException, MethodNotAllowed, \
     NotImplemented, NotFound
from werkzeug.serving import run_simple
from jinja2 import Environment,FileSystemLoader

class Request(BaseRequest):
    """对请求进行包装,可以自定义"""

class Response(BaseResponse):
    """对返回值进行包装,可以自定义."""

class View(object):
    """视图的基本类"""
    def __init__(self):
        self.methods = {
            'GET': self.GET,
            'POST': self.POST,
            'PUT': self.PUT,
            'DELETE': self.DELETE,
        }
    def GET(self):
        raise MethodNotAllowed()
    POST = DELETE = PUT = GET

    def HEAD(self):
        return self.GET()
    def dispatch_request(self, request, *args, **options):
        if request.method in self.methods:
            return self.methods[request.method](request, *args, **options)
        else:
            return '<h1>不支持的请求方式!</h1>'

    @classmethod
    def get_func(cls):
        # 匹配视图函数
        def func(*args, **kwargs):
            obj = func.view_class()
            return obj.dispatch_request(*args, **kwargs)
        func.view_class = cls
        return func

class App(object):
    def __init__(self):
        self.url_map = {} # 记录url和视图函数的对应关系

    def wsgi_app(self,environ,start_response):
        req = Request(environ)
        response = self.dispatch_request(req) #进行请求的分发
        if response:#如果可以找到正确的匹配项
            response = Response(response, content_type='text/html; charset=UTF-8')
        else:#找不到,返回404NotFound
            response = Response('<h1>404 Not Found<h1>', content_type='text/html; charset=UTF-8', status=404)
        return response(environ, start_response)

    def __call__(self, environ, start_response):
        return self.wsgi_app(environ, start_response)

    def dispatch_request(self, req):
        try:
            url = req.path
            view = self.url_map.get(url,None)
            if view:
                response = view(req)
            else:
                response = None
        except HTTPException as e:
            response = e
        return response
    def add_url_rule(self,urls):
         for url in urls:
             self.url_map[url] = urls[url].get_func()

    def run(self, port=8090, ip='127.0.0.1', debug=True):
        #运行使用的是werkzeug的run_simple所创建的服务器
        run_simple(ip, port, self, use_debugger=debug, use_reloader=True)

测试:

from app import App,View,session
import json

class Index(View):
    def GET(self,request):
        return "hello world"
    def POST(self,request):
        # print(json.dumps(request.form['color']))
        return json.dumps({'1':'hello'})

class Test(View):
    def GET(self,request):
        return 'test'
    def POST(self,request):
        return json.dumps({'2':'hello'})

urls = {'/':Index,
        '/test':Test}

app = App()
app.add_url_rule(urls)
app.run()

测试GET方法结果:

在这里插入图片描述
测试POST方法:

在这里插入图片描述
参考:
https://github.com/pallets/werkzeug/blob/0.12.2/examples/webpylike/webpylike.py

全部评论

相关推荐

面试官全程关摄像头1.自我介绍一下2.React和Vue哪个更熟悉一点3.你在之前那段实习经历中有没有什么技术性的突破(我只是实习了44天工作28天,我把我能说的都说了)4.你封装的哪个表单组件支不支持动态传值5.自己在实习阶段Vue3项目封装过hook吗6.hook有什么作用7.Vue2和Vue3的响应式区别(我说一个是proxy是拦截所有的底层操作,Object.defineProperty本身就是一个底层操作,有些东西拦截不了,比如数组的一些操作还有等等,面试官就说实在要拦截能不能拦截????我心想肯定不行呀,他的底层机制就不允许吧)8.pinia和vuex的区别(这个回答不出来是我太久没用了)9.pinia和zustand的区别,怎么选(直接给我干懵了)(我说react能用pinia吗&nbsp;&nbsp;他说要用的话也可以)10.渲染一万条数据,怎么解决页面卡顿问题(我说分页、监听滚轮动态加载,纯数据展示好像还可以用canvas画)(估计是没说虚拟表单,感觉不满意)11.type和interface的区别12.ts的泛型有哪些作用(我就说了一个结构相同但是类型不同的时候可以用,比如请求响应的接口,每次的data不同,这里能用一个泛型,他问我还有什么)13.你项目用的是React,如果让你再写一遍你会选择什么14.pnpm、npm、yarn的区别15.dependencies和devdependencies的区别总而言之太久没面试了,上一段实习的面试js问了很多。结果这次js一点没问,网络方面也没考,表现得很一般,但是知道自己的问题了&nbsp;&nbsp;好好准备,等待明天的影石360和周四的腾讯了&nbsp;&nbsp;加油!!!
解zj:大三的第一段面试居然是这样的结局
查看15道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务