登录  | 加入社区

黑狼游客您好!登录后享受更多精彩

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

查看: 370|回复: 0

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

[复制链接]

13

主题

0

帖子

0

现金

黑狼菜鸟

Rank: 1

积分
0
发表于 2017-12-5 18:10:57 | 显示全部楼层 |阅读模式 来自 美国
您的域名(hlsh.sh)未得到授权,部门功能受到影响!


尊重的用户:

  您好!非常感谢您能安装和关注本产物,为了产物的可连续发展和升级,众大云收罗已经开始收费。

  向用户收费是为了给用户更可靠的保障和服务,所收取的费用重要用于产物的正常运作、研发和改进,盼望各位可以或许明白和支持。

  别的,为了报答新老客户,众大云收罗3折优惠,原价980元,如今购买仅需290元,给您节流了690元。

  官方QQ群:23530791  客服QQ:155120699

  购买域名授权请打开下面的网址:

http://www.0762home.com/zt/csdn123_news/pay_url.php?url=hlsh.sh

  购买域名授权之后全部的未授权提示将主动消散,图片也正常表现,域名授权永世有用终身可用,后续的升级更新也是免费的,一次购买一辈子都能用,无后顾之忧!

提示:您现在利用的是免费试用版,可以手动删除上面的授权提示,发布这篇文章!


(点击上方蓝字,快速关注我们)



泉源: 开源中国
www.oschina.net/translate/django-flask-pyramid
如有好文章投稿,请点击 → 这里相识详情


Pyramid, Django, 和 Flask都是良好的框架,为项目选择此中的哪一个都是伤头脑的事。我们将会用三种框架实现雷同功能的应用来更轻易的对比三者。也可以直接跳到框架实战(Frameworks in Action)章节检察代码(code)。


1 简介


天下上可选的基于Python的web框架有许多。Django, Flask, Pyramid, Tornado, Bottle, Diesel, Pecan, Falcon等等,都在夺取开辟者支持。作为一开辟者从一堆选择中筛选出一个来完成项目将会成为下一个大工程。我们本日专注于Flask, Pyramid, 和 Django。它们涵盖了从小微项目到企业级的web服务。


为了更轻易在三者中作出选择(至少更相识它们),我们将用每一个框架构建同样的应用并比力它们的代码,对于每一个方法我们会高亮表现它的长处和缺点。假如你只想要代码,直接跳到框架实战章节(Frameworks in Action),大概检察其在Github上的代码。


Flask是一个面向简朴需求小型应用的“微框架(microframework)”。Pyramid和Django都是面向大型应用的,但是有差别的拓展性和机动性。Pyramid的目标是更机动,可以或许让开辟者为项目选择符合的工具。这意味着开辟者可以或许选择数据库、URL布局、模板范例等等。Django目标是席卷web应用的全部内容,以是开辟者只必要打开箱子开始工作,将Django的模块拉进箱子中。


Django包罗一个开箱即用的 ORM ,而Pyramid和 Flask让开辟者本身选择怎样大概是否存储他们的数据。到现在为止对于非Django的web应用来说最盛行的ORM是SQLAlchemy,同时另有多种其他选择,从 DynamoDB和MongoDB 到简朴当地存储的LevelDB 或朴素的SQLite。Pyramid被计划为可利用任何数据长期层,乃至是还没有开辟出来的。


2、关于框架


Django的”batteries included” 特性让开辟者不必要提前为他们的应用步伐底子办法做决定,由于他们知道Python已经深入到了web应用当中。Django已经内建了模板、表单、路由、认证、根本数据库管理等等。比力起来,Pyramid包罗路由和认证,但是模板和数据库管理必要额外的库。


前面为 Flask和Pyramid apps选择组件的额外工作给那些利用案例不实用尺度ORM的开辟者提供了更多的机动性,同样也给利用差别工作流和模版化体系的开辟者们带来了机动性。


Flask,作为三个框架内里最稚气的一个,开始于2010年年中。Pyramid框架是从Pylons项目开始的,在2010年底得到 Pyramid这个名字,固然在2005年就已经发布了第一个版本。Django 2006年发布了第一个版本,就在Pylons项目(末了叫Pyramid)开始之后。Pyramid和Django都黑白常成熟的框架,积聚了浩繁插件和扩展以满意难以置信的巨大需求。


固然Flask汗青相对更短,但它可以或许学习之前出现的框架而且把留意力放在了微小项目上。它大多数环境被利用在一些只有一两个功能的小型项目上。比方 httpbin,一个简朴的(但很强盛的)调试和测试HTTP库的项目。


3. 社区


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


三个框架都利用的是BSD衍生的协议。Flask和Django的协议是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行代码就够了。


[color=#999999 !important]# from http://flask.pocoo.org/ tutorial
from[color=#006FE0 !important] [color=teal !important]flask import[color=#006FE0 !important] [color=teal !important]Flask
[color=#002D7A !important]app[color=#006FE0 !important] = [color=teal !important]Flask[color=#333333 !important]([color=#002D7A !important]__name__[color=#333333 !important])
 
[color=#333333 !important]@[color=#002D7A !important]app[color=#333333 !important].[color=teal !important]route[color=#333333 !important]([color=#DD1144 !important]"/"[color=#333333 !important])[color=#006FE0 !important] [color=#999999 !important]# take note of this decorator syntax, it's a common pattern
def[color=#006FE0 !important] [color=teal !important]hello[color=#333333 !important]()[color=#006FE0 !important]:
[color=#006FE0 !important]    return[color=#006FE0 !important] [color=#DD1144 !important]"Hello World!"
 
if[color=#006FE0 !important] [color=#002D7A !important]__name__[color=#006FE0 !important] == [color=#DD1144 !important]"__main__"[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]app[color=#333333 !important].[color=teal !important]run[color=#333333 !important]()


这是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专用工具链替换了。


$ pcreate -s starter hello_pyramid # Just make a Pyramid project


Pyramid 比 Flask 实用于更大更复杂的应用步伐. 由于这一点,它的 bootstrapping工具创建更大的项目骨架. Pyramid 同样参加了根本的设置文件,一个例子模版和用于将步伐打包上传到 Python Package Index的全部文件。


[color=#002D7A !important]hello[color=#333333 !important]_pyramid
├──[color=#006FE0 !important] [color=#002D7A !important]CHANGES[color=#333333 !important].txt
├──[color=#006FE0 !important] [color=#002D7A !important]development[color=#333333 !important].ini
├──[color=#006FE0 !important] [color=#002D7A !important]MANIFEST[color=#333333 !important].in
├──[color=#006FE0 !important] [color=#002D7A !important]production[color=#333333 !important].ini
├──[color=#006FE0 !important] [color=#002D7A !important]hello[color=#333333 !important]_pyramid
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]__init__[color=#333333 !important].py
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] static
│[color=#006FE0 !important]   │[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]pyramid[color=#006FE0 !important]-[color=#009999 !important]16x16.png
│[color=#006FE0 !important]   │[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]pyramid[color=#333333 !important].png
│[color=#006FE0 !important]   │[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]theme[color=#333333 !important].css
│[color=#006FE0 !important]   │[color=#006FE0 !important]   └──[color=#006FE0 !important] [color=#002D7A !important]theme[color=#333333 !important].[color=teal !important]min[color=#333333 !important].css
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] templates
│[color=#006FE0 !important]   │[color=#006FE0 !important]   └──[color=#006FE0 !important] [color=#002D7A !important]mytemplate[color=#333333 !important].pt
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]tests[color=#333333 !important].py
│[color=#006FE0 !important]   └──[color=#006FE0 !important] [color=#002D7A !important]views[color=#333333 !important].py
├──[color=#006FE0 !important] [color=#002D7A !important]README[color=#333333 !important].txt
└──[color=#006FE0 !important] [color=#002D7A !important]setup[color=#333333 !important].[color=#002D7A !important]py


作为末了形貌的框架,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 中.


[color=#002D7A !important]django[color=#006FE0 !important]-[color=teal !important]admin startproject hello_django
[color=#002D7A !important]django[color=#006FE0 !important]-[color=teal !important]admin startapp [color=#002D7A !important]howdy[color=#006FE0 !important] [color=#999999 !important]# make an application within our project


Django 跟 Pyramid 区别在于: Django 由多个应用步伐构成一个项目, 而 Pyramid 以及 Flask 项目是包罗 View 和 Model 单一应用步伐 . 理论上, Flask 和 Pyramid 的项目答应存在多个 project/app, 不外在默认设置中只能有一个.


[color=#002D7A !important]hello[color=#333333 !important]_django
├──[color=#006FE0 !important] [color=#002D7A !important]hello[color=#333333 !important]_django
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]__init__[color=#333333 !important].py
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]settings[color=#333333 !important].py
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]urls[color=#333333 !important].py
│[color=#006FE0 !important]   └──[color=#006FE0 !important] [color=#002D7A !important]wsgi[color=#333333 !important].py
├──[color=#006FE0 !important] howdy
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]admin[color=#333333 !important].py
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]__init__[color=#333333 !important].py
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] migrations
│[color=#006FE0 !important]   │[color=#006FE0 !important]   └──[color=#006FE0 !important] [color=#002D7A !important]__init__[color=#333333 !important].py
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]models[color=#333333 !important].py
│[color=#006FE0 !important]   ├──[color=#006FE0 !important] [color=#002D7A !important]tests[color=#333333 !important].py
│[color=#006FE0 !important]   └──[color=#006FE0 !important] [color=#002D7A !important]views[color=#333333 !important].py
└──[color=#006FE0 !important] [color=#002D7A !important]manage[color=#333333 !important].[color=#002D7A !important]py


Django 默认只在项目中创建 空缺的 model 和模板文件, 供新手参考的树模代码不多. 别的, 开辟者在发布应用步伐的时间, 还要本身设置, 这也是个贫苦.


bootstrap 工具的缺点是没有引导开辟者怎样打包应用. 对于那些没有履历的新手来说, 第一次摆设应用将是个很头疼的题目. 像 django-oscar 如许的大社区, 项目都是打包好了, 放在 PyPi 上供各人安装. 但是 Github 上面的小项目缺少同一的打包方式.


5 模板


一个Python应用可以或许相应HTTP哀求将是一个巨大的开端,但是有大概你的大多数用户是没有爱好利用curl与你的web应用交互的。荣幸的是,这三个竞争者提供了利用自界说信息添补HTML的方法,以便让大伙们可以或许享受时髦的Bootstrap 前端。


模板让你可以或许直接向页面注入动态信息,而不是接纳AJAX。你只必要一次哀求就可以获取整个页面以及全部的动态数据,这对用户体验来说是很好的。这对于手机网站来说尤其紧张,由于一次哀求耗费的时间会更长。


全部的模板选项依靠于“上下文情况(context)”,其为模板转换为HTML提供了动态信息。模板的最简朴的例子是添补已登任命户的名字以精确的欢迎他们。也可以用AJAX获取这种动态信息,但是用一整个调用来填写用户的名字有点过头了,而同时模板又是这么的简朴。


5.1 Django


我们利用的例子正如写的那么简朴,假设我们有一个包罗了用户名的funllname属性的user对象。在Python中我们如许向模板中通报当前用户:


def[color=#006FE0 !important] [color=teal !important]a_view[color=#333333 !important]([color=#002D7A !important]request[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#999999 !important]# get the logged in user
[color=#006FE0 !important]    [color=#999999 !important]# ... do more things
[color=#006FE0 !important]    return[color=#006FE0 !important] [color=teal !important]render_to_response[color=#333333 !important](
[color=#006FE0 !important]        [color=#DD1144 !important]"view.html"[color=#333333 !important],
[color=#006FE0 !important]        [color=#333333 !important]{[color=#DD1144 !important]"user"[color=#006FE0 !important]: [color=#002D7A !important]cur_user[color=#333333 !important]}
[color=#006FE0 !important]    [color=#333333 !important])


拥有这个模板的上下文很简朴,传入一个Python对象的字典和模板利用的数据布局。如今我们必要在页面上渲染他们的名字,以防页面忘了他们是谁。


[color=#006FE0 !important]
[color=#006FE0 !important]
[color=#006FE0 !important]  
[color=#006FE0 !important]  
[color=#006FE0 !important]  
[color=#006FE0 !important]  [color=#333333 !important]{[color=#006FE0 !important]% if[color=#006FE0 !important] [color=teal !important]user[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important]  
[color=#006FE0 !important]    [color=teal !important]You[color=#006FE0 !important] [color=teal !important]are[color=#006FE0 !important] [color=teal !important]logged[color=#006FE0 !important] in[color=#006FE0 !important] as[color=#006FE0 !important] [color=#333333 !important]{{[color=#006FE0 !important] [color=teal !important]user[color=#333333 !important].fullname[color=#006FE0 !important] [color=#333333 !important]}}
[color=#006FE0 !important]  
[color=#006FE0 !important]  [color=#333333 !important]{[color=#006FE0 !important]% [color=#002D7A !important]endif[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important]


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


在if块内,你可以看到,包罗名字非常的简朴,只要用{{}}包罗着我们要插入的属性就可以了。{{是用来向模板插入真实值的,如{{ user.fullname }}。


模板的另一个常用环境是展示一组物品,如一个电子商务网站的存货清单页面。


def[color=#006FE0 !important] [color=teal !important]browse_shop[color=#333333 !important]([color=#002D7A !important]request[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#999999 !important]# get items
[color=#006FE0 !important]    return[color=#006FE0 !important] [color=teal !important]render_to_response[color=#333333 !important](
[color=#006FE0 !important]        [color=#DD1144 !important]"browse.html"[color=#333333 !important],
[color=#006FE0 !important]        [color=#333333 !important]{[color=#DD1144 !important]"inventory"[color=#006FE0 !important]: [color=#002D7A !important]all_items[color=#333333 !important]}
[color=#006FE0 !important]    [color=#333333 !important])


在模板中,我们利用同样的{%来循环清单中的全部条目,并填入它们各自的页面地点。


[color=#333333 !important]{[color=#006FE0 !important]% for[color=#006FE0 !important] [color=teal !important]widget in[color=#006FE0 !important] [color=#002D7A !important]inventory[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important]    [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]widget[color=#333333 !important].displayname[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important]
[color=#333333 !important]{[color=#006FE0 !important]% [color=#002D7A !important]endfor[color=#006FE0 !important] %[color=#333333 !important]}


为了做大部门常见的模板使命,Django可以仅仅利用很少的布局来完成目的,因此很轻易上手。


5.2 Flask


Flask默认利用受Django开导的Jinja2模板语言,但也可以设置来利用另一门语言。不应该诉苦一个匆匆的步伐员分不清Django和Jinja模板。究竟是,上面的Django例子在Jinja2也有用。为了不去重复雷同的例子,我们来看下Jinja2比Django模板更具体现力的地方。


Jinja和Django模板都提够了过滤的特性,即传入的列表会在展示前通过一个函数。一个拥有博文种别属性的博客,可以使用过滤特性,在一个用逗号分割的列表中展示博文的种别。


[color=#006FE0 !important]
[color=#006FE0 !important][color=#002D7A !important]Categories[color=#006FE0 !important]: [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]post[color=#333333 !important].[color=#002D7A !important]categories[color=#006FE0 !important]|[color=#002D7A !important]join[color=#006FE0 !important]:[color=#DD1144 !important]", "[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important]
 
[color=#006FE0 !important]
[color=#006FE0 !important][color=#002D7A !important]Categories[color=#006FE0 !important]: [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]post[color=#333333 !important].[color=#002D7A !important]categories[color=#006FE0 !important]|[color=teal !important]join[color=#333333 !important]([color=#DD1144 !important]", "[color=#333333 !important])[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important]


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


Jinjia和Django的for循环有点雷同。我们来看看他们的差别。在Jinjia2中,for-else-endfor布局能遍历一个列表,同时也处置惩罚了没有项的环境。


[color=#333333 !important]{[color=#006FE0 !important]% for[color=#006FE0 !important] [color=teal !important]item in[color=#006FE0 !important] [color=#002D7A !important]inventory[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important][color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]item[color=#333333 !important].[color=teal !important]render[color=#333333 !important]()[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important]
[color=#333333 !important]{[color=#006FE0 !important]% else[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important]
[color=#006FE0 !important][color=teal !important]No items [color=#002D7A !important]found[color=#006FE0 !important]
[color=#006FE0 !important]Try[color=#006FE0 !important] [color=teal !important]another [color=#002D7A !important]search[color=#333333 !important],[color=#006FE0 !important] [color=teal !important]maybe[color=#333333 !important]?[color=#006FE0 !important]
[color=#006FE0 !important]
[color=#333333 !important]{[color=#006FE0 !important]% [color=#002D7A !important]endfor[color=#006FE0 !important] %[color=#333333 !important]}


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


[color=#333333 !important]{[color=#006FE0 !important]% for[color=#006FE0 !important] [color=teal !important]item in[color=#006FE0 !important] [color=#002D7A !important]inventory[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important][color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]item[color=#333333 !important].render[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important]
[color=#333333 !important]{[color=#006FE0 !important]% [color=#002D7A !important]empty[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important]
[color=#006FE0 !important][color=teal !important]No items [color=#002D7A !important]found[color=#006FE0 !important]
[color=#006FE0 !important]Try[color=#006FE0 !important] [color=teal !important]another [color=#002D7A !important]search[color=#333333 !important],[color=#006FE0 !important] [color=teal !important]maybe[color=#333333 !important]?[color=#006FE0 !important]
[color=#006FE0 !important]
[color=#333333 !important]{[color=#006FE0 !important]% [color=#002D7A !important]endfor[color=#006FE0 !important] %[color=#333333 !important]}


除了语法上的差别,Jinja2通过实行情况和高级特性提供了更多的控制。比方,它可以关闭伤害的特性以安全的实行不受信托的模板,大概提前编译模板以确保它们的正当性。


5.3 Pyramid


与Flask雷同,Pyramid支持多种模板语言(包罗Jinja2和Mako),但是默认只附带一个。Pyramid利用Chameleon,一个 ZPT (Zope Page Template) 模板语言的实现。我们来转头看看第一个例子,添加用户的名字到网站的顶栏。Python代码除了明白调用了render_template函数外其他看起来都差不多。


[color=#333333 !important]@[color=teal !important]view_config[color=#333333 !important]([color=#002D7A !important]renderer[color=#006FE0 !important]=[color=#DD1144 !important]'templates/home.pt'[color=#333333 !important])
def[color=#006FE0 !important] [color=teal !important]my_view[color=#333333 !important]([color=#002D7A !important]request[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#999999 !important]# do stuff...
[color=#006FE0 !important]    return[color=#006FE0 !important] [color=#333333 !important]{[color=#DD1144 !important]'user'[color=#006FE0 !important]: [color=teal !important]user[color=#333333 !important]}


但是我们的模板看起来有些差别。ZPT是一个基于XML得模板尺度,以是我们利用了类XSLT语句来操纵数据。


[color=#006FE0 !important]
[color=#006FE0 !important]  
[color=#006FE0 !important]  
[color=#006FE0 !important]  
[color=#006FE0 !important]  
[color=#006FE0 !important]  
[color=#006FE0 !important]


Chameleon对于模板操纵有三种差别的定名空间。TAL(模板属性语言)提供了根本的条件语句,字符串的格式化,以及添补标签内容。上面的例子只用了TAL来完成相干工作。对于更多高级使命,就必要TALES和METAL。TALES( 模板属性表达式语法的语言)提供了像高级字符串格式化,Python表达式评估,以及导入表达式和模板的表达式。


METAL(宏扩展模板属性语言)是Chameleon模板最强盛的(和复杂的)一部门。宏是可扩展的,并能被界说为带有槽且当宏被调用时可以被添补。


6. 使用框架举措起来


对于各个框架,我们将通过制作一个叫做wut4lunch的应用来相识,这个应用是告诉整个互联网你午饭吃了什么的交际网络。很自由的一个起始想法,完全可以随意改变。应用将有一个简朴的接口,答应用户提交他们午饭的内容,并看到其他用户吃的什么的列表。主页完成后将看起来像如许。


lC3Z6JC0y0LC5Y3L.jpg
6.1 利用Flask的Demo应用


最短的实现用了34行Python代码和一个22行的Jinja模板。起首,我们有些管理类的使命要做,好比初始化我们的应用并拉近我们的ORM。


from[color=#006FE0 !important] [color=teal !important]flask import[color=#006FE0 !important] [color=#002D7A !important]Flask
 
[color=#999999 !important]# For this example we'll use SQLAlchemy, a popular ORM that supports a
[color=#999999 !important]# variety of backends including SQLite, MySQL, and PostgreSQL
from[color=#006FE0 !important] [color=#002D7A !important]flask[color=#333333 !important].[color=#002D7A !important]ext[color=#333333 !important].[color=teal !important]sqlalchemy import[color=#006FE0 !important] [color=teal !important]SQLAlchemy
 
[color=#002D7A !important]app[color=#006FE0 !important] = [color=teal !important]Flask[color=#333333 !important]([color=#002D7A !important]__name__[color=#333333 !important])
[color=#999999 !important]# We'll just use SQLite here so we don't need an external database
[color=#002D7A !important]app[color=#333333 !important].[color=#002D7A !important]config[color=#333333 !important][[color=#DD1144 !important]'SQLALCHEMY_DATABASE_URI'[color=#333333 !important]][color=#006FE0 !important] = [color=#DD1144 !important]'sqlite:///test.db'
 
[color=#002D7A !important]db[color=#006FE0 !important] = [color=teal !important]SQLAlchemy[color=#333333 !important]([color=#002D7A !important]app[color=#333333 !important])


如今我们看下我们的模子,这将和另两个样例根本一样。


[color=#800080 !important]class[color=#006FE0 !important] [color=teal !important]Lunch[color=#333333 !important]([color=#002D7A !important]db[color=#333333 !important].[color=#002D7A !important]Model[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#DD1144 !important]"""A single lunch"""
[color=#006FE0 !important]    [color=teal !important]id[color=#006FE0 !important] = [color=#002D7A !important]db[color=#333333 !important].[color=teal !important]Column[color=#333333 !important]([color=#002D7A !important]db[color=#333333 !important].[color=#002D7A !important]Integer[color=#333333 !important],[color=#006FE0 !important] [color=#002D7A !important]primary_key[color=#006FE0 !important]=[color=#800080 !important]True[color=#333333 !important])
[color=#006FE0 !important]    [color=#002D7A !important]submitter[color=#006FE0 !important] = [color=#002D7A !important]db[color=#333333 !important].[color=teal !important]Column[color=#333333 !important]([color=#002D7A !important]db[color=#333333 !important].[color=teal !important]String[color=#333333 !important]([color=#009999 !important]63[color=#333333 !important]))
[color=#006FE0 !important]    [color=#002D7A !important]food[color=#006FE0 !important] = [color=#002D7A !important]db[color=#333333 !important].[color=teal !important]Column[color=#333333 !important]([color=#002D7A !important]db[color=#333333 !important].[color=teal !important]String[color=#333333 !important]([color=#009999 !important]255[color=#333333 !important]))


哇,相称简朴。最难的部门是找到符合的 SQLAlchemy数据范例,选择数据库中String域的长度。利用我们的模子也超等简朴,这在于我们将要看到 SQLAlchemy查询语法。


构建我们的提交表单也很简朴。在引入Flask-WTForms和精确的域范例后,你可以看到表单看起来有点像我们的模子。重要的区别在于新的提交按钮和食品与提交者姓名域的提示。


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


from[color=#006FE0 !important] [color=#002D7A !important]flask[color=#333333 !important].[color=#002D7A !important]ext[color=#333333 !important].[color=teal !important]wtf import[color=#006FE0 !important] [color=teal !important]Form
from[color=#006FE0 !important] [color=#002D7A !important]wtforms[color=#333333 !important].[color=teal !important]fields import[color=#006FE0 !important] [color=#002D7A !important]StringField[color=#333333 !important],[color=#006FE0 !important] [color=teal !important]SubmitField
 
[color=#002D7A !important]app[color=#333333 !important].[color=#002D7A !important]config[color=#333333 !important][[color=#DD1144 !important]'SECRET_KEY'[color=#333333 !important]][color=#006FE0 !important] = [color=#DD1144 !important]'please, tell nobody'
 
[color=#800080 !important]class[color=#006FE0 !important] [color=teal !important]LunchForm[color=#333333 !important]([color=#002D7A !important]Form[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]submitter[color=#006FE0 !important] = [color=teal !important]StringField[color=#333333 !important](u[color=#DD1144 !important]'Hi, my name is'[color=#333333 !important])
[color=#006FE0 !important]    [color=#002D7A !important]food[color=#006FE0 !important] = [color=teal !important]StringField[color=#333333 !important](u[color=#DD1144 !important]'and I ate'[color=#333333 !important])
[color=#006FE0 !important]    [color=#999999 !important]# submit button will read "share my lunch!"
[color=#006FE0 !important]    [color=#002D7A !important]submit[color=#006FE0 !important] = [color=teal !important]SubmitField[color=#333333 !important](u[color=#DD1144 !important]'share my lunch!'[color=#333333 !important])


让表单在欣赏器中显表示味着模板要有它。我们像下面那样通报进去。


from[color=#006FE0 !important] [color=teal !important]flask import[color=#006FE0 !important] [color=#002D7A !important]render[color=#333333 !important]_template
 
[color=#333333 !important]@[color=#002D7A !important]app[color=#333333 !important].[color=teal !important]route[color=#333333 !important]([color=#DD1144 !important]"/"[color=#333333 !important])
def[color=#006FE0 !important] [color=teal !important]root[color=#333333 !important]()[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]lunches[color=#006FE0 !important] = [color=#002D7A !important]Lunch[color=#333333 !important].[color=#002D7A !important]query[color=#333333 !important].[color=teal !important]all[color=#333333 !important]()
[color=#006FE0 !important]    [color=#002D7A !important]form[color=#006FE0 !important] = [color=teal !important]LunchForm[color=#333333 !important]()
[color=#006FE0 !important]    return[color=#006FE0 !important] [color=teal !important]render_template[color=#333333 !important]([color=#DD1144 !important]'index.html'[color=#333333 !important],[color=#006FE0 !important] [color=#002D7A !important]form[color=#006FE0 !important]=[color=#002D7A !important]form[color=#333333 !important],[color=#006FE0 !important] [color=#002D7A !important]lunches[color=#006FE0 !important]=[color=#002D7A !important]lunches[color=#333333 !important])


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


[color=#006FE0 !important]
[color=#006FE0 !important]Wut[color=#006FE0 !important] [color=#009999 !important]4[color=#006FE0 !important] [color=#002D7A !important]Lunch[color=#006FE0 !important]
[color=#006FE0 !important][color=teal !important]What are people [color=#002D7A !important]eating[color=#333333 !important]?[color=#006FE0 !important]
 
[color=#006FE0 !important][color=teal !important]Wut4Lunch is[color=#006FE0 !important] [color=teal !important]the latest social network where you can tell all[color=#006FE0 !important] [color=teal !important]your friends
[color=teal !important]about your noontime [color=#002D7A !important]repast[color=#006FE0 !important]!


这就是模板的真实环境,我们在已经吃过的午餐中循环,并在<ul>中展示他们。这险些与我们前面看到的循环例子一样。


[color=#006FE0 !important]
[color=#333333 !important]{[color=#006FE0 !important]% for[color=#006FE0 !important] [color=teal !important]lunch in[color=#006FE0 !important] [color=#002D7A !important]lunches[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important][color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]lunch[color=#333333 !important].[color=#002D7A !important]submitter[color=#006FE0 !important]|safe[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important] [color=teal !important]just[color=#006FE0 !important] [color=teal !important]ate[color=#006FE0 !important] [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]lunch[color=#333333 !important].[color=#002D7A !important]food[color=#006FE0 !important]|safe[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important]
[color=#333333 !important]{[color=#006FE0 !important]% else[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important][color=teal !important]Nobody has eaten [color=#002D7A !important]lunch[color=#333333 !important],[color=#006FE0 !important] [color=teal !important]you[color=#006FE0 !important] [color=teal !important]must[color=#006FE0 !important] [color=teal !important]all[color=#006FE0 !important] [color=teal !important]be[color=#006FE0 !important] [color=teal !important]starving[color=#006FE0 !important]!
[color=#333333 !important]{[color=#006FE0 !important]% [color=#002D7A !important]endfor[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important]
 
[color=#006FE0 !important][color=teal !important]What are YOU [color=#002D7A !important]eating[color=#333333 !important]?[color=#006FE0 !important]
 
[color=#006FE0 !important]
[color=#006FE0 !important]    [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]form[color=#333333 !important].[color=teal !important]hidden_tag[color=#333333 !important]()[color=#006FE0 !important] [color=#333333 !important]}}
[color=#006FE0 !important]    [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]form[color=#333333 !important].[color=#002D7A !important]submitter[color=#333333 !important].label[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important] [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]form[color=#333333 !important].[color=teal !important]submitter[color=#333333 !important]([color=#002D7A !important]size[color=#006FE0 !important]=[color=#009999 !important]40[color=#333333 !important])[color=#006FE0 !important] [color=#333333 !important]}}
[color=#006FE0 !important]    
[color=#006FE0 !important]    [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]form[color=#333333 !important].[color=#002D7A !important]food[color=#333333 !important].label[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important] [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]form[color=#333333 !important].[color=teal !important]food[color=#333333 !important]([color=#002D7A !important]size[color=#006FE0 !important]=[color=#009999 !important]50[color=#333333 !important])[color=#006FE0 !important] [color=#333333 !important]}}
[color=#006FE0 !important]    
[color=#006FE0 !important]    [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]form[color=#333333 !important].submit[color=#006FE0 !important] [color=#333333 !important]}}
[color=#006FE0 !important]
[color=#006FE0 !important]


模板的部门仅仅渲染我们在root()视图中传入模板的WTForm对象的表单标签和输入。当表单提交时,它将向/new提交一个POST哀求,这个哀求会被下面的函数处置惩罚。


from[color=#006FE0 !important] [color=teal !important]flask import[color=#006FE0 !important] [color=#002D7A !important]url_for[color=#333333 !important],[color=#006FE0 !important] redirect
 
[color=#333333 !important]@[color=#002D7A !important]app[color=#333333 !important].[color=teal !important]route[color=#333333 !important](u[color=#DD1144 !important]'/new'[color=#333333 !important],[color=#006FE0 !important] [color=#002D7A !important]methods[color=#006FE0 !important]=[color=#333333 !important][u[color=#DD1144 !important]'POST'[color=#333333 !important]])
def[color=#006FE0 !important] [color=teal !important]newlunch[color=#333333 !important]()[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]form[color=#006FE0 !important] = [color=teal !important]LunchForm[color=#333333 !important]()
[color=#006FE0 !important]    if[color=#006FE0 !important] [color=#002D7A !important]form[color=#333333 !important].[color=teal !important]validate_on_submit[color=#333333 !important]()[color=#006FE0 !important]:
[color=#006FE0 !important]        [color=#002D7A !important]lunch[color=#006FE0 !important] = [color=teal !important]Lunch[color=#333333 !important]()
[color=#006FE0 !important]        [color=#002D7A !important]form[color=#333333 !important].[color=teal !important]populate_obj[color=#333333 !important]([color=#002D7A !important]lunch[color=#333333 !important])
[color=#006FE0 !important]        [color=#002D7A !important]db[color=#333333 !important].[color=#002D7A !important]session[color=#333333 !important].[color=teal !important]add[color=#333333 !important]([color=#002D7A !important]lunch[color=#333333 !important])
[color=#006FE0 !important]        [color=#002D7A !important]db[color=#333333 !important].[color=#002D7A !important]session[color=#333333 !important].[color=teal !important]commit[color=#333333 !important]()
[color=#006FE0 !important]    return[color=#006FE0 !important] [color=teal !important]redirect[color=#333333 !important]([color=teal !important]url_for[color=#333333 !important]([color=#DD1144 !important]'root'[color=#333333 !important]))


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


if[color=#006FE0 !important] [color=#002D7A !important]__name__[color=#006FE0 !important] == [color=#DD1144 !important]"__main__"[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]db[color=#333333 !important].[color=teal !important]create_all[color=#333333 !important]()[color=#006FE0 !important]  [color=#999999 !important]# make our sqlalchemy tables
[color=#006FE0 !important]    [color=#002D7A !important]app[color=#333333 !important].[color=teal !important]run[color=#333333 !important]()


末了,我们只需做(非常)少量的工作来让应用运行起来。利用SQLAlchemy,我们可以创建存储午餐的表,然后开始运行我们写的路径管理就行了。


6.2 测试Django版APP


Django版wut4lunch 和Flask版有点像,但是在Django项目中被分到了好几个文件中。起首,我们看看最相似的部门:数据库模子。它和SQLAlchemy版本的唯一差别之处是声明生存文本的数据库字段有稍微的语法区别。


[color=#999999 !important]# from wut4lunch/models.py
from[color=#006FE0 !important] [color=#002D7A !important]django[color=#333333 !important].[color=teal !important]db import[color=#006FE0 !important] [color=teal !important]models
 
[color=#800080 !important]class[color=#006FE0 !important] [color=teal !important]Lunch[color=#333333 !important]([color=#002D7A !important]models[color=#333333 !important].[color=#002D7A !important]Model[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]submitter[color=#006FE0 !important] = [color=#002D7A !important]models[color=#333333 !important].[color=teal !important]CharField[color=#333333 !important]([color=#002D7A !important]max_length[color=#006FE0 !important]=[color=#009999 !important]63[color=#333333 !important])
[color=#006FE0 !important]    [color=#002D7A !important]food[color=#006FE0 !important] = [color=#002D7A !important]models[color=#333333 !important].[color=teal !important]CharField[color=#333333 !important]([color=#002D7A !important]max_length[color=#006FE0 !important]=[color=#009999 !important]255[color=#333333 !important])


在表单体系上。不像Flask,我们可以用Django内建的表单体系。它看起来非常像我们在Flask中利用的WTFroms模块,只是语法有点差别。


from[color=#006FE0 !important] [color=teal !important]django import[color=#006FE0 !important] [color=teal !important]forms
from[color=#006FE0 !important] [color=#002D7A !important]django[color=#333333 !important].[color=teal !important]http import[color=#006FE0 !important] [color=teal !important]HttpResponse
from[color=#006FE0 !important] [color=#002D7A !important]django[color=#333333 !important].[color=teal !important]shortcuts import[color=#006FE0 !important] [color=#002D7A !important]render[color=#333333 !important],[color=#006FE0 !important] [color=teal !important]redirect
 
from[color=#006FE0 !important] [color=#333333 !important].[color=teal !important]models import[color=#006FE0 !important] [color=#002D7A !important]Lunch
 
[color=#999999 !important]# Create your views here.
 
[color=#800080 !important]class[color=#006FE0 !important] [color=teal !important]LunchForm[color=#333333 !important]([color=#002D7A !important]forms[color=#333333 !important].[color=#002D7A !important]Form[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#DD1144 !important]"""Form object. Looks a lot like the WTForms Flask example"""
[color=#006FE0 !important]    [color=#002D7A !important]submitter[color=#006FE0 !important] = [color=#002D7A !important]forms[color=#333333 !important].[color=teal !important]CharField[color=#333333 !important]([color=#002D7A !important]label[color=#006FE0 !important]=[color=#DD1144 !important]'Your name'[color=#333333 !important])
[color=#006FE0 !important]    [color=#002D7A !important]food[color=#006FE0 !important] = [color=#002D7A !important]forms[color=#333333 !important].[color=teal !important]CharField[color=#333333 !important]([color=#002D7A !important]label[color=#006FE0 !important]=[color=#DD1144 !important]'What did you eat?'[color=#333333 !important])


如今我们只必要构造一个LunchForm实例通报到我们的模板。


[color=#002D7A !important]lunch_form[color=#006FE0 !important] = [color=teal !important]LunchForm[color=#333333 !important]([color=#002D7A !important]auto_id[color=#006FE0 !important]=[color=#800080 !important]False[color=#333333 !important])
 
def[color=#006FE0 !important] [color=teal !important]index[color=#333333 !important]([color=#002D7A !important]request[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]lunches[color=#006FE0 !important] = [color=#002D7A !important]Lunch[color=#333333 !important].[color=#002D7A !important]objects[color=#333333 !important].[color=teal !important]all[color=#333333 !important]()
[color=#006FE0 !important]    return[color=#006FE0 !important] [color=teal !important]render[color=#333333 !important](
[color=#006FE0 !important]        [color=#002D7A !important]request[color=#333333 !important],
[color=#006FE0 !important]        [color=#DD1144 !important]'wut4lunch/index.html'[color=#333333 !important],
[color=#006FE0 !important]        [color=#333333 !important]{
[color=#006FE0 !important]            [color=#DD1144 !important]'lunches'[color=#006FE0 !important]: [color=#002D7A !important]lunches[color=#333333 !important],
[color=#006FE0 !important]            [color=#DD1144 !important]'form'[color=#006FE0 !important]: [color=#002D7A !important]lunch_form[color=#333333 !important],
[color=#006FE0 !important]        [color=#333333 !important]}
[color=#006FE0 !important]    [color=#333333 !important])


render函数是Django shortcut,以担当哀求、模板路径和一个上下文的dict。与Flask的render_template雷同,它也担当接入哀求。


def[color=#006FE0 !important] [color=teal !important]newlunch[color=#333333 !important]([color=#002D7A !important]request[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]l[color=#006FE0 !important] = [color=teal !important]Lunch[color=#333333 !important]()
[color=#006FE0 !important]    [color=#002D7A !important]l[color=#333333 !important].[color=#002D7A !important]submitter[color=#006FE0 !important] = [color=#002D7A !important]request[color=#333333 !important].[color=#002D7A !important]POST[color=#333333 !important][[color=#DD1144 !important]'submitter'[color=#333333 !important]]
[color=#006FE0 !important]    [color=#002D7A !important]l[color=#333333 !important].[color=#002D7A !important]food[color=#006FE0 !important] = [color=#002D7A !important]request[color=#333333 !important].[color=#002D7A !important]POST[color=#333333 !important][[color=#DD1144 !important]'food'[color=#333333 !important]]
[color=#006FE0 !important]    [color=#002D7A !important]l[color=#333333 !important].[color=teal !important]save[color=#333333 !important]()
[color=#006FE0 !important]    return[color=#006FE0 !important] [color=teal !important]redirect[color=#333333 !important]([color=#DD1144 !important]'home'[color=#333333 !important])


生存表单应答到数据库是不一样的,Django调用模子的 .save()方法以及处置惩罚会话管理而不是用全局数据库会话。干净利落!


Django提供了一些优雅的特性,让我们管理用户提交的午餐,因此我们可以删除那些不符合的午餐信息。Flask和Pyramid没有主动提供这些功能,而在创建一个Django应用时不必要写另一个管理页面固然也是其一个特性。开辟者的时间可难免费啊!我们所要做的就是告诉Django-admin我们的模子,是在wut5lunch/admin.py中添加两行。


from[color=#006FE0 !important] [color=#002D7A !important]wut4lunch[color=#333333 !important].[color=teal !important]models import[color=#006FE0 !important] [color=teal !important]Lunch
[color=#002D7A !important]admin[color=#333333 !important].[color=teal !important]site[color=#333333 !important].[color=teal !important]register[color=#333333 !important]([color=#002D7A !important]Lunch[color=#333333 !important])


Bam。如今我们可以添加删除一些条目,而无需额外的工作。


末了,让我们看下主页模板的差别之处。


[color=#006FE0 !important]
[color=#333333 !important]{[color=#006FE0 !important]% for[color=#006FE0 !important] [color=teal !important]lunch in[color=#006FE0 !important] [color=#002D7A !important]lunches[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important][color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]lunch[color=#333333 !important].submitter[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important] [color=teal !important]just[color=#006FE0 !important] [color=teal !important]ate[color=#006FE0 !important] [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]lunch[color=#333333 !important].food[color=#006FE0 !important] [color=#333333 !important]}}[color=#006FE0 !important]
[color=#333333 !important]{[color=#006FE0 !important]% [color=#002D7A !important]empty[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important][color=teal !important]Nobody has eaten [color=#002D7A !important]lunch[color=#333333 !important],[color=#006FE0 !important] [color=teal !important]you[color=#006FE0 !important] [color=teal !important]must[color=#006FE0 !important] [color=teal !important]all[color=#006FE0 !important] [color=teal !important]be[color=#006FE0 !important] [color=teal !important]starving[color=#006FE0 !important]!
[color=#333333 !important]{[color=#006FE0 !important]% [color=#002D7A !important]endfor[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important]


Django拥有方便的快捷方式,在你的页面中引用其他的视图。url标签可以使你重修应用中的URLs,而不需粉碎视图。这个是由于url标签会自动查询视图中的URL。


[color=#006FE0 !important]
[color=#006FE0 !important]  [color=#333333 !important]{[color=#006FE0 !important]% [color=#002D7A !important]csrf_token[color=#006FE0 !important] %[color=#333333 !important]}
[color=#006FE0 !important]  [color=#333333 !important]{{[color=#006FE0 !important] [color=#002D7A !important]form[color=#333333 !important].[color=#002D7A !important]as[color=#333333 !important]_ul[color=#006FE0 !important] [color=#333333 !important]}}
[color=#006FE0 !important]  
[color=#006FE0 !important]


表单被差别的语法渲染,我们必要人工在表单主体中添加CSRF token,但这些区别更多的是装饰


6.3测试Pyramid版App


末了,我们看看用Pyramid实现的同样的步伐。与Django和Flask的最大差别是模板。只必要对Jinja2做很小的改动就足以办理我们在Django中的题目。这次不是如许的,Pyramid的Chameleon模板的语法更轻易让人遐想到XSLT而不是别的。


[color=#006FE0 !important]
[color=#006FE0 !important]
[color=#006FE0 !important]  
[color=#006FE0 !important]    
[color=#006FE0 !important]      
[color=#006FE0 !important]    
[color=#006FE0 !important]  
[color=#006FE0 !important]
[color=#006FE0 !important]
[color=#006FE0 !important]  [color=teal !important]Nobody has eaten [color=#002D7A !important]lunch[color=#333333 !important],[color=#006FE0 !important] [color=teal !important]you must all[color=#006FE0 !important] [color=teal !important]be [color=#002D7A !important]starving[color=#006FE0 !important]!
[color=#006FE0 !important]


与Django模板雷同,缺少for-else-endfor布局使得逻辑轻微的更清楚了。这种环境下,我们以if-for 和 if-not-for 语句块末端以提供同样的功能。利用{{或{%来控制布局和条件的Django以及AngularJS范例的模板让利用XHTML标签的模板显得很生手。


Chameleon模板范例的一大利益是你所选择的编辑器可以精确的使语法高亮,由于模板是有些得XHTML。对于Django和Flask模板来说,你的编辑器必要可以或许精确的支持这些模板语言高亮表现。


[color=#006FE0 !important][color=teal !important]What are YOU [color=#002D7A !important]eating[color=#333333 !important]?[color=#006FE0 !important]
 
[color=#006FE0 !important]
[color=#006FE0 !important]  [color=#002D7A !important]Name[color=#006FE0 !important]: [color=#333333 !important]${[color=#002D7A !important]form[color=#333333 !important].[color=teal !important]text[color=#333333 !important]([color=#DD1144 !important]"submitter"[color=#333333 !important],[color=#006FE0 !important] [color=#002D7A !important]size[color=#006FE0 !important]=[color=#009999 !important]40[color=#333333 !important])}
[color=#006FE0 !important]  
[color=#006FE0 !important]  [color=teal !important]What[color=#006FE0 !important] [color=teal !important]did[color=#006FE0 !important] [color=teal !important]you[color=#006FE0 !important] [color=teal !important]eat[color=#333333 !important]?[color=#006FE0 !important] [color=#333333 !important]${[color=#002D7A !important]form[color=#333333 !important].[color=teal !important]text[color=#333333 !important]([color=#DD1144 !important]"food"[color=#333333 !important],[color=#006FE0 !important] [color=#002D7A !important]size[color=#006FE0 !important]=[color=#009999 !important]40[color=#333333 !important])}
[color=#006FE0 !important]  
[color=#006FE0 !important]  
[color=#006FE0 !important]
[color=#006FE0 !important]


Pyramid中表单得转换轻微更过细些,由于pytamid_simpleform不像Django表单的form.as_ul函数那样可以主动转换全部的表单字段。


如今我们看看什么返回给应用。起首,界说我们必要得表单并出现我们的主页。


[color=#999999 !important]# pyramid_wut4lunch/views.py
[color=#800080 !important]class[color=#006FE0 !important] [color=teal !important]LunchSchema[color=#333333 !important]([color=#002D7A !important]Schema[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]submitter[color=#006FE0 !important] = [color=#002D7A !important]validators[color=#333333 !important].[color=teal !important]UnicodeString[color=#333333 !important]()
[color=#006FE0 !important]    [color=#002D7A !important]food[color=#006FE0 !important] = [color=#002D7A !important]validators[color=#333333 !important].[color=teal !important]UnicodeString[color=#333333 !important]()
 
[color=#333333 !important]@[color=teal !important]view_config[color=#333333 !important]([color=#002D7A !important]route_name[color=#006FE0 !important]=[color=#DD1144 !important]'home'[color=#333333 !important],
[color=#006FE0 !important]             [color=#002D7A !important]renderer[color=#006FE0 !important]=[color=#DD1144 !important]'templates/index.pt'[color=#333333 !important])
def[color=#006FE0 !important] [color=teal !important]home[color=#333333 !important]([color=#002D7A !important]request[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]lunches[color=#006FE0 !important] = [color=#002D7A !important]DBSession[color=#333333 !important].[color=teal !important]query[color=#333333 !important]([color=#002D7A !important]Lunch[color=#333333 !important]).[color=teal !important]all[color=#333333 !important]()
[color=#006FE0 !important]    [color=#002D7A !important]form[color=#006FE0 !important] = [color=teal !important]Form[color=#333333 !important]([color=#002D7A !important]request[color=#333333 !important],[color=#006FE0 !important] [color=#002D7A !important]schema[color=#006FE0 !important]=[color=teal !important]LunchSchema[color=#333333 !important]())
[color=#006FE0 !important]    return[color=#006FE0 !important] [color=#333333 !important]{[color=#DD1144 !important]'lunches'[color=#006FE0 !important]: [color=#002D7A !important]lunches[color=#333333 !important],[color=#006FE0 !important] [color=#DD1144 !important]'form'[color=#006FE0 !important]: [color=teal !important]FormRenderer[color=#333333 !important]([color=#002D7A !important]form[color=#333333 !important])}


获取午餐的查询语法和Flask的很相似,这是由于这两个demo应用利用了盛行的SQLAlchemy ORM来提供长期存储。在Pyramid中,答应你直接返回模板上下文的字典,而不是要调用特别的render函数。@view_config装饰器主动将返回的上下文传入要渲染的模板。制止调用render方法使得Pyramid写的函数更加轻易测试,由于它们返回的数据没有被模板渲染对象掩饰。


[color=#333333 !important]@[color=teal !important]view_config[color=#333333 !important]([color=#002D7A !important]route_name[color=#006FE0 !important]=[color=#DD1144 !important]'newlunch'[color=#333333 !important],
[color=#006FE0 !important]             [color=#002D7A !important]renderer[color=#006FE0 !important]=[color=#DD1144 !important]'templates/index.pt'[color=#333333 !important],
[color=#006FE0 !important]             [color=#002D7A !important]request_method[color=#006FE0 !important]=[color=#DD1144 !important]'POST'[color=#333333 !important])
def[color=#006FE0 !important] [color=teal !important]newlunch[color=#333333 !important]([color=#002D7A !important]request[color=#333333 !important])[color=#006FE0 !important]:
[color=#006FE0 !important]    [color=#002D7A !important]l[color=#006FE0 !important] = [color=teal !important]Lunch[color=#333333 !important](
[color=#006FE0 !important]        [color=#002D7A !important]submitter[color=#006FE0 !important]=[color=#002D7A !important]request[color=#333333 !important].[color=#002D7A !important]POST[color=#333333 !important].[color=teal !important]get[color=#333333 !important]([color=#DD1144 !important]'submitter'[color=#333333 !important],[color=#006FE0 !important] [color=#DD1144 !important]'nobody'[color=#333333 !important]),
[color=#006FE0 !important]        [color=#002D7A !important]food[color=#006FE0 !important]=[color=#002D7A !important]request[color=#333333 !important].[color=#002D7A !important]POST[color=#333333 !important].[color=teal !important]get[color=#333333 !important]([color=#DD1144 !important]'food'[color=#333333 !important],[color=#006FE0 !important] [color=#DD1144 !important]'nothing'[color=#333333 !important]),
[color=#006FE0 !important]    [color=#333333 !important])
 
[color=#006FE0 !important]    with[color=#006FE0 !important] [color=#002D7A !important]transaction[color=#333333 !important].[color=#002D7A !important]manager[color=#006FE0 !important]:
[color=#006FE0 !important]        [color=#002D7A !important]DBSession[color=#333333 !important].[color=teal !important]add[color=#333333 !important]([color=#002D7A !important]l[color=#333333 !important])
 
[color=#006FE0 !important]    raise[color=#006FE0 !important] [color=#002D7A !important]exc[color=#333333 !important].[color=teal !important]HTTPSeeOther[color=#333333 !important]([color=#DD1144 !important]'/'[color=#333333 !important])


从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的批评和修正(名字按字母表次序)。


看完本文有劳绩?请转发分享给更多人

关注「Python开辟者」,提拔Python技能

AVtlLPX4Cz4tpxrK.jpg




上一篇:游戏很神奇吗,花12分钟看一下​Python​怎么做一个简朴的小游戏 ...
下一篇:为什么你应该学 Python ?
您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

 

QQ|申请友链|小黑屋|手机版|Hlshell Inc. ( 豫ICP备16002110号-5 )

GMT+8, 2024-5-14 10:01 , Processed in 0.076758 second(s), 47 queries .

HLShell有权修改版权声明内容,如有任何爭議,HLShell將保留最終決定權!

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表