选择一个 Python Web 框架:Django vs Flask vs Pyramid

Pyramid, Django, 和 Flask都是优秀的框架,为项目选择其中的哪个都是伤脑筋的事。咱们将会用三种框架实现相同功能的应用来更容易的对比三者。也能够直接跳到框架实战(Frameworks in Action)章节查看代码(code)。css

1 简介

世界上可选的基于Python的web框架有不少。Django, Flask, Pyramid, Tornado, Bottle, Diesel, Pecan, Falcon等等,都在争取开发者支持。做为一开发者从一堆选择中筛选出一个来完成项目将会成为下一个大工程。咱们今天专一于Flask, Pyramid, 和 Django。它们涵盖了从小微项目到企业级的web服务。html

为了更容易在三者中做出选择(至少更了解它们),咱们将用每个框架构建一样的应用并比较它们的代码,对于每个方法咱们会高亮显示它的优势和缺点。若是你只想要代码,直接跳到框架实战章节(Frameworks in Action),或者查看其在Github上的代码。前端

Flask是一个面向简单需求小型应用的“微框架(microframework)”。Pyramid和Django都是面向大型应用的,可是有不一样的拓展性和灵活性。Pyramid的目的是更灵活,可以让开发者为项目选择合适的工具。这意味着开发者可以选择数据库、URL结构、模板类型等等。Django目的是囊括web应用的全部内容,因此开发者只须要打开箱子开始工做,将Django的模块拉进箱子中。python

Django包括一个开箱即用的 ORM ,而Pyramid和 Flask让开发者本身选择如何或者是否存储他们的数据。到目前为止对于非Django的web应用来讲最流行的ORM是SQLAlchemy,同时还有多种其余选择,从 DynamoDBMongoDB 到简单本地存储的LevelDB 或朴实的SQLite。Pyramid被设计为可以使用任何数据持久层,甚至是尚未开发出来的。git

二、关于框架

Django的”batteries included” 特性让开发者不须要提早为他们的应用程序基础设施作决定,由于他们知道Python已经深刻到了web应用当中。Django已经内建了模板、表单、路由、认证、基本数据库管理等等。比较起来,Pyramid包括路由和认证,可是模板和数据库管理须要额外的库。程序员

前面为 Flask和Pyramid apps选择组件的额外工做给那些使用案例不适用标准ORM的开发者提供了更多的灵活性,一样也给使用不一样工做流和模版化系统的开发者们带来了灵活性。github

Flask,做为三个框架里面最稚气的一个,开始于2010年年中。Pyramid框架是从Pylons项目开始的,在2010年末得到 Pyramid这个名字,虽然在2005年就已经发布了第一个版本。Django 2006年发布了第一个版本,就在Pylons项目(最后叫Pyramid)开始以后。Pyramid和Django都是很是成熟的框架,积累了众多插件和扩展以知足难以置信的巨大需求。web

虽然Flask历史相对更短,但它可以学习以前出现的框架而且把注意力放在了微小项目上。它大多数状况被使用在一些只有一两个功能的小型项目上。例如 httpbin,一个简单的(但很强大的)调试和测试HTTP库的项目。sql

3. 社区

最具活力的社区当属Django,其有80,000个StackOverflow问题和一系列来自开发者和优秀用户的良好的博客。Flask和Pyramid社区并无那么大,但它们的社区在邮件列表和IRC上至关活跃。StackOverflow上仅有5,000个相关的标签,Flask比Django小了15倍。在Github上,它们的star近乎至关,Django有11,300个,Flask有10,900个。mongodb

三个框架都使用的是BSD衍生的协议。FlaskDjango的协议是BSD 3条款,Pyramid的Repoze Public License RPL是BSD协议 4条款的衍生。

4. Bootstrapping

Django和Pyramid都内建bootstrapping工具。Flask没有包含相似的工具,由于Flask的目标用户不是那种试图构建大型MVC应用的人。

4.1 Flask

Flask的hello world应用很是的简单,仅仅单个Python文件的7行代码就够了。

这是Flask没有bootstrapping工具的缘由:没有它们的需求。从Flask主页上的Hello World特性看,没有构建Python web应用经验的开发者能够当即开始hacking。

对于各部分须要更多分离的项目,Flask有blueprints。例如,你能够将全部用户相关的函数放在users.py中,将销售相关的函数放在ecommerce.py中,而后在site.py中添加引用它们来结构化你的Flask应用。咱们不会深刻这个功能,由于它超出了咱们展现demo应用的需求。

4.2 Pyramid

Pyramid 的 bootstrapping工具叫 pcreate,是Pyramid的组成部分. 以前的 Paste 工具套装提供了 bootstrapping ,可是从那以后被 Pyramid专用工具链替代了。

Pyramid 比 Flask 适用于更大更复杂的应用程序. 由于这一点,它的 bootstrapping工具建立更大的项目骨架. Pyramid 一样加入了基本的配置文件,一个例子模版和用于将程序打包上传到 Python Package Index的全部文件。

做为最后描述的框架,Pyramid的bootstrapper很是灵活. 不局限于一个默认的程序;pcreate 可使用任意数量的项目模版. 包括咱们上面用到的pcreate里面的”starter”的模版, 还有 SQLAlchemy- ,ZODB-支持scaffold项目. 在 PyPi能够发现已经为Google App Engine, jQuery Mobile, Jinja2 templating, modern frontend frameworks作好的scaffolds, 还有更多~

4.3 Django

Django 也有本身的 bootstrap 工具, 内置在 django-admin 中.

Django 跟 Pyramid 区别在于: Django 由多个应用程序组成一个项目, 而 Pyramid 以及 Flask 项目是包含 View 和 Model 单一应用程序 . 理论上, Flask 和 Pyramid 的项目容许存在多个 project/app, 不过在默认配置中只能有一个.

Django 默认只在项目中建立 空白的 model 和模板文件, 供新手参考的示范代码很少. 此外, 开发者在发布应用程序的时候, 还要本身配置, 这也是个麻烦.

bootstrap 工具的缺点是没有指导开发者如何打包应用. 对于那些没有经验的新手来讲, 第一次部署应用将是个很头疼的问题. 像 django-oscar 这样的大社区, 项目都是打包好了, 放在 PyPi 上供你们安装. 可是 Github 上面的小项目缺乏统一的打包方式.

5 模板

一个Python应用可以响应HTTP请求将是一个伟大的开端,可是有可能你的大多数用户是没有兴趣使用curl与你的web应用交互的。幸运的是,这三个竞争者提供了使用自定义信息填充HTML的方法,以便让大伙们可以享受时髦的Bootstrap 前端。

模板让你可以直接向页面注入动态信息,而不是采用AJAX。你只须要一次请求就能够获取整个页面以及全部的动态数据,这对用户体验来讲是很好的。这对于手机网站来讲尤为重要,由于一次请求花费的时间会更长。

全部的模板选项依赖于“上下文环境(context)”,其为模板转换为HTML提供了动态信息。模板的最简单的例子是填充已登陆用户的名字以正确的迎接他们。也能够用AJAX获取这种动态信息,可是用一整个调用来填写用户的名字有点过头了,而同时模板又是这么的简单。

5.1 Django

咱们使用的例子正如写的那么简单,假设咱们有一个包含了用户名的funllname属性的user对象。在Python中咱们这样向模板中传递当前用户:

拥有这个模板的上下文很简单,传入一个Python对象的字典和模板使用的数据结构。如今咱们须要在页面上渲染他们的名字,以防页面忘了他们是谁。

首先,你会注意到这个 {% if user %} 概念。在Django模板中, {% 用来控制循环和条件的声明。这里的if user声明是为了防止那些不是用户的状况。匿名用户不该该在页面头部看到“你已经登陆”的字样。

在if块内,你能够看到,包含名字很是的简单,只要用{{}}包含着咱们要插入的属性就能够了。{{是用来向模板插入真实值的,如{{ user.fullname }}。

模板的另外一个经常使用状况是展现一组物品,如一个电子商务网站的存货清单页面。

在模板中,咱们使用一样的{%来循环清单中的全部条目,并填入它们各自的页面地址。

为了作大部分常见的模板任务,Django能够仅仅使用不多的结构来完成目标,所以很容易上手。

5.2 Flask

Flask默认使用受Django启发的Jinja2模板语言,但也能够配置来使用另外一门语言。不该该抱怨一个仓促的程序员分不清Django和Jinja模板。事实是,上面的Django例子在Jinja2也有效。为了避免去重复相同的例子,咱们来看下Jinja2比Django模板更具表现力的地方。

Jinja和Django模板都提够了过滤的特性,即传入的列表会在展现前经过一个函数。一个拥有博文类别属性的博客,能够利用过滤特性,在一个用逗号分割的列表中展现博文的类别。

在Jinja模板语言中,能够向过滤器传入任意数量的参数,由于Jinja把它当作是 使用括号包含参数的Python函数的一个调用。Django使用冒号来分割过滤器的名字和过滤参数,这限制了参数的数目只能为一。

Jinjia和Django的for循环有点相似。咱们来看看他们的不一样。在Jinjia2中,for-else-endfor结构能遍历一个列表,同时也处理了没有项的状况。

Django版的这个功能是同样的,可是是用for-empty-endfor而不是for-else-endfor。

除了语法上的不一样,Jinja2经过执行环境和高级特性提供了更多的控制。例如,它能够关闭危险的特性以安全的执行不受信任的模板,或者提早编译模板以确保它们的合法性。

5.3 Pyramid

与Flask相似,Pyramid支持多种模板语言(包括Jinja2和Mako),可是默认只附带一个。Pyramid使用Chameleon,一个 ZPT (Zope Page Template) 模板语言的实现。咱们来回头看看第一个例子,添加用户的名字到网站的顶栏。Python代码除了明确调用了render_template函数外其余看起来都差很少。

可是咱们的模板看起来有些不一样。ZPT是一个基于XML得模板标准,因此咱们使用了类XSLT语句来操做数据。

Chameleon对于模板操做有三种不一样的命名空间。TAL(模板属性语言)提供了基本的条件语句,字符串的格式化,以及填充标签内容。上面的例子只用了TAL来完成相关工做。对于更多高级任务,就须要TALES和METAL。TALES( 模板属性表达式语法的语言)提供了像高级字符串格式化,Python表达式评估,以及导入表达式和模板的表达式。

METAL(宏扩展模板属性语言)是Chameleon模板最强大的(和复杂的)一部分。宏是可扩展的,并能被定义为带有槽且当宏被调用时能够被填充。

6. 利用框架行动起来

对于各个框架,咱们将经过制做一个叫作wut4lunch的应用来了解,这个应用是告诉整个互联网你午餐吃了什么的社交网络。很自由的一个起始想法,彻底能够随意改变。应用将有一个简单的接口,容许用户提交他们午餐的内容,并看到其余用户吃的什么的列表。主页完成后将看起来像这样。

cpp_py_medium

6.1 使用Flask的Demo应用

最短的实现用了34行Python代码和一个22行的Jinja模板。首先,咱们有些管理类的任务要作,好比初始化咱们的应用并拉近咱们的ORM。

如今咱们看下咱们的模型,这将和另两个样例基本同样。

哇,至关简单。最难的部分是找到合适的 SQLAlchemy数据类型,选择数据库中String域的长度。使用咱们的模型也超级简单,这在于咱们将要看到 SQLAlchemy查询语法
构建咱们的提交表单也很简单。在引入Flask-WTForms和正确的域类型后,你能够看到表单看起来有点像咱们的模型。主要的区别在于新的提交按钮和食物与提交者姓名域的提示。

应用中的SECRET_KEY域是被WTForms用来建立CSRF符号的。它也被itsdangerous(Flask内包含)用来设置cookies和其余数据。

让表单在浏览器中显示意味着模板要有它。咱们像下面那样传递进去。

好了,发生了什么?咱们获得已经用Lunch.query.all()提交的午饭列表,并实例化一个表单,让用户提交他们本身的美食之旅。为了简化,变量使用相同的名字出入模板,但这不是必须的。

这就是模板的真实状况,咱们在已经吃过的午饭中循环,并在<ul>中展现他们。这几乎与咱们前面看到的循环例子同样。

模板的<form>部分仅仅渲染咱们在root()视图中传入模板的WTForm对象的表单标签和输入。当表单提交时,它将向/new提交一个POST请求,这个请求会被下面的函数处理。

在验证了表单数据后,咱们把内容放入咱们Model对象中,并提交到数据库。一旦咱们在数据库中存了午饭,它将在人们吃过的午饭列表中出现。

最后,咱们只需作(很是)少许的工做来让应用运行起来。使用SQLAlchemy,咱们能够建立存储午饭的表,而后开始运行咱们写的路径管理就好了。

6.2 测试Django版APP

Django版wut4lunch 和Flask版有点像,可是在Django项目中被分到了好几个文件中。首先,咱们看看最类似的部分:数据库模型。它和SQLAlchemy版本的惟一不一样之处是声明保存文本的数据库字段有轻微的语法区别。

在表单系统上。不像Flask,咱们能够用Django内建的表单系统。它看起来很是像咱们在Flask中使用的WTFroms模块,只是语法有点不一样。

如今咱们只须要构造一个LunchForm实例传递到咱们的模板。

render函数是Django shortcut,以接受请求、模板路径和一个上下文的dict。与Flask的render_template相似,它也接受接入请求。

保存表单应答到数据库是不同的,Django调用模型的 .save()方法以及处理会话管理而不是用全局数据库会话。干净利落!

Django提供了一些优雅的特性,让咱们管理用户提交的午饭,所以咱们能够删除那些不合适的午饭信息。Flask和Pyramid没有自动提供这些功能,而在建立一个Django应用时不须要写另外一个管理页面固然也是其一个特性。开发者的时间可难免费啊!咱们所要作的就是告诉Django-admin咱们的模型,是在wut5lunch/admin.py中添加两行。

Bam。如今咱们能够添加删除一些条目,而无需额外的工做。

最后,让咱们看下主页模板的不一样之处。

Django拥有方便的快捷方式,在你的页面中引用其余的视图。url标签可使你重建应用中的URLs,而不需破坏视图。这个是由于url标签会主动查询视图中的URL。

表单被不一样的语法渲染,咱们须要人工在表单主体中添加CSRF token,但这些区别更多的是装饰

6.3测试Pyramid版App

最后,咱们看看用Pyramid实现的一样的程序。与Django和Flask的最大不一样是模板。只须要对Jinja2作很小的改动就足以解决咱们在Django中的问题。此次不是这样的,Pyramid的Chameleon模板的语法更容易让人联想到XSLT而不是别的。

与Django模板相似,缺乏for-else-endfor结构使得逻辑稍微的更清晰了。这种状况下,咱们以if-for 和 if-not-for 语句块结尾以提供一样的功能。使用{{或{%来控制结构和条件的Django以及AngularJS类型的模板让使用XHTML标签的模板显得很外行。

Chameleon模板类型的一大好处是你所选择的编辑器能够正确的使语法高亮,由于模板是有些得XHTML。对于Django和Flask模板来讲,你的编辑器须要可以正确的支持这些模板语言高亮显示。

Pyramid中表单得转换稍微更细致些,由于pytamid_simpleform不像Django表单的form.as_ul函数那样能够自动转换全部的表单字段。

如今咱们看看什么返回给应用。首先,定义咱们须要得表单并呈现咱们的主页。

获取午饭的查询语法和Flask的很类似,这是由于这两个demo应用使用了流行的SQLAlchemy ORM来提供持久存储。在Pyramid中,容许你直接返回模板上下文的字典,而不是要调用特殊的render函数。@view_config装饰器自动将返回的上下文传入要渲染的模板。避免调用render方法使得Pyramid写的函数更加容易测试,由于它们返回的数据没有被模板渲染对象掩盖。

从Pyramid的请求对象中更加容易获得表单数据,由于在咱们获取时会自动将表单POST数据解析成dict。为了阻止同一时间多并发的请求数据库,ZopeTransactions模块提供了上下文管理器,对写入逻辑事物的数据库进行分组,并阻止应用的线程在各个改变时互相影响,这在你的视图共享一个全局session并接收到大量通讯的状况下将会是个问题。

7. 总结

Pyramid是三个中最灵活的。它能够用于小的应用,正如咱们所见,但它也支撑着有名的网站如Dropbox。开源社区如Fedora选择它开发应用,如他们社区中的徽章系统,从项目工具中接受事件的信息,并向用户奖励成就类型的徽章。对于Pyramid的一个最多见的抱怨是,它提供了这么多的选项,以致于用它开始一个新项目很吓人。

目前最流行的框架是Django,使用它的网站列表也使人印象深入。Bitbucket,Pinterest,Instagram,以及Onion彻底或部分使用Django。对于有常见需求的网站,Django是很是理智的选择,也所以它成为中大型网站应用的流行选择。

Flask对于那些开发小项目、须要快速制做一个简单的Python支撑的网站的开发者颇有用。它提供小型的统一工具,或者在已有的API上构建的简单网络接口。能够快速开发须要简单web接口并不怎么配置的后端项目使用Flask将会在前端获益,如jitviewer提供了一个web接口来检测PyPy just-in-time的编译日志。

这三个框架都能解决咱们简单的需求,咱们已经看到了它们的不一样。这些区别不只仅是装饰性的,它们将会改变你设计产品的方法,以及添加新特性和修复的速度。由于咱们的例子很小,咱们看到Flask的闪光点,以及Django在小规模应用上的笨重。Pyramid的灵活并未体现出来,由于咱们的要求是同样的,但在真实场景中,新的需求会经常出现。

7.1 致谢

标题图像的logo来自与Flask、Django和Pyramid项目网站。

这篇文章很是感谢它的评阅者,Remy DeCausemaker,Ross Delinger和Liam Middlebrook,忍受了许多初期的草稿。

这篇文章的当前样式来自于Adam Chainz、bendwarn、Serger Maertens、Tom Leo和wichert的评论和修正(名字按字母表顺序)。

相关文章
相关标签/搜索