为学习目的而构建的python web框架。
alcazar-web-framework的Python项目详细描述
阿尔卡扎尔
alcazar是一个用于学习的python web框架。计划是通过实现框架的特性来学习如何构建框架, 写关于它们的博客文章并尽可能简单地保持代码库。
它是一个wsgi框架,可以与任何wsgi应用服务器(如gunicorn)一起使用。
灵感
在阅读了Florimond Monca的blog post之后,我被启发去制作一个web框架。 关于他如何构建一个web框架并成为一个开源维护者。他写了这段经历对他来说是多么的激动人心,所以我决定也试试看。 谢谢,Florimond当然还有Kenneth Reitz他反过来启发了Florimond用 他自己的框架。去看看Bocadillo by Florimond Monca和Responder by Kenneth Reitz。 如果你喜欢他们,就盯着他们的照片来表达你的爱。
博客文章
- Part I: Intro, API, request handlers, routing (both simple and parameterized)
- Part II: class based handlers, route overlap check, unit tests
- Part III: templates support, test client, django way of adding routes
- Part IV: custom exception handler, support for static files, middleware
快速启动
安装:
pip install alcazar-web-framework
基本用法:
# app.pyfromalcazarimportAlcazarapp=Alcazar()@app.route("/")defhome(req,resp):resp.text="Hello, this is a home page."@app.route("/about")defabout_page(req,resp):resp.text="Hello, this is an about page."@app.route("/{age:d}")deftell_age(req,resp,age):resp.text=f"Your age is {age}"@app.route("/{name:l}")classGreetingHandler:defget(self,req,resp,name):resp.text=f"Hello, {name}"@app.route("/show/template")defhandler_with_template(req,resp):resp.html=app.template("example.html",context={"title":"Awesome Framework","body":"welcome to the future!"})@app.route("/json")defjson_handler(req,resp):resp.json={"this":"is JSON"}@app.route("/custom")defcustom_response(req,resp):resp.body=b'any other body'resp.content_type="text/plain"
开始时间:
gunicorn app:app
处理程序
如果使用基于类的处理程序,则只允许您实现的方法:
@app.route("/{name:l}")classGreetingHandler:defget(self,req,resp,name):resp.text=f"Hello, {name}"
此处理程序只允许GET
请求。也就是说,POST
和其他的将被拒绝。同样的事情也可以用
按以下方式基于函数的处理程序:
@app.route("/",methods=["get"])defhome(req,resp):resp.text="Hello, this is a home page."
注意,如果为基于类的处理程序指定methods
,它们将被忽略。
单元测试
编写单元测试的推荐方法是使用pytest。有两个内置装置
使用alcazar编写单元测试时可能要使用的。第一个是app
,它是主Alcazar
类的一个实例:
deftest_route_overlap_throws_exception(app):@app.route("/")defhome(req,resp):resp.text="Welcome Home."withpytest.raises(AssertionError):@app.route("/")defhome2(req,resp):resp.text="Welcome Home2."
另一个是client
,您可以使用它向处理程序发送http请求。它是根据著名的requests改编的,应该会让人感觉非常熟悉:
deftest_parameterized_route(app,client):@app.route("/{name}")defhello(req,resp,name):resp.text=f"hey {name}"assertclient.get(url("/matthew")).text=="hey matthew"
注意,使用了一个url()
函数。它用于生成给定相对url的请求的绝对url。使用前导入:
fromalcazar.utils.testsimporturl
模板
模板的默认文件夹是templates
。您可以在初始化主Alcazar()
类时更改它:
app=Alcazar(templates_dir="templates_dir_name")
然后您可以像在处理程序中那样使用该文件夹中的HTML文件:
@app.route("/show/template")defhandler_with_template(req,resp):resp.html=app.template("example.html",context={"title":"Awesome Framework","body":"welcome to the future!"})
静态文件
与模板一样,静态文件的默认文件夹是static
,您可以覆盖它:
app=Alcazar(static_dir="static_dir_name")
然后您可以在HTML文件中使用此文件夹中的文件:
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>{{title}}</title><linkhref="/static/main.css"rel="stylesheet"type="text/css"></head><body><h1>{{body}}</h1><p>This is a paragraph</p></body></html>
自定义异常处理程序
有时,根据引发的异常,您可能需要执行特定操作。对于这种情况,您可以注册异常处理程序:
defon_exception(req,resp,exception):ifisinstance(exception,HTTPError):ifexception.status==404:resp.text="Unfortunately the thing you were looking for was not found"else:resp.text=str(exception)else:# unexpected exceptionsifapp.debug:debug_exception_handler(req,resp,exception)else:print("These unexpected exceptions should be logged.")app=Alcazar(debug=False)app.add_exception_handler(on_exception)
此异常处理程序将捕获404个httperrors并将文本更改为"Unfortunately the thing you were looking for was not found"
。对于其他httperrors,它将
显示异常消息。如果引发的异常不是httperror,并且debug
设置为true,则它将显示异常及其回溯。否则,它会记录下来。
中间件
通过继承alcazar.middleware.Middleware
类并重写其两个方法,可以创建自定义中间件类
在每个请求之前和之后调用:
fromalcazarimportAlcazarfromalcazar.middlewareimportMiddlewareapp=Alcazar()classSimpleCustomMiddleware(Middleware):defprocess_request(self,req):print("Before dispatch",req.url)defprocess_response(self,req,res):print("After dispatch",req.url)app.add_middleware(SimpleCustomMiddleware)
功能
- 与wsgi兼容
- 基本和参数化布线
- 基于类的处理程序
- 测试客户端
- 支持模板
- 支持静态文件
- 自定义异常处理程序
- 中间件
注
这是非常原始的,希望会继续改进。如果您有兴趣了解如何在其他 框架,请打开一个问题,我们将希望实现和解释它在博客文章。