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

全部评论

相关推荐

05-26 16:13
门头沟学院 C++
牢大肘击Java:海投就完事了bro,就当刷视频了
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
今天 12:31
以前小时候我最痛恨出轨、偷情的人,无论男女,为什么会出轨?现在我成了自己最讨厌的人,没想到分享的东西在牛客会被这么多人看,大家的评价都很中肯,我也认同,想过一一回复,但我还是收声了,我想我应该说说这件事,这件事一直压在我心里,是个很大的心结,上面说了人为什么出轨,我大概能明白了。我们大一下半年开始恋爱,开始恋爱,我给出了我铭记3年的承诺,我对她好一辈子,我永远不会背叛,我责任心太重,我觉得跟了我,我就要照顾她一辈子,我们在一起3年我都没有碰过她,她说往东我就往东,她说什么我做什么,她要我干什么,我就干什么!在学校很美好,中途也出过一些小插曲,比如男闺蜜、男闺蜜2号等等等。但我都强迫她改掉了,我...
牛客刘北:两个缺爱的人是没有办法好好在一起的,但世界上哪有什么是非对错?你后悔你们在一起了,但是刚刚在一起的美好也是真的呀,因为其他人的出现,你开始想要了最开始的自己,你的确对不起自己,21岁的你望高物远,你完全可以不谈恋爱,去过你想要的生活,你向往自由,在一起之后,你要想的不是一个人,而是两个人,你不是变心了,就像你说的,你受够了,你不想包容了,冷静几天是你最优的选择,爱人先爱己。
社会教会你的第一课
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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