Django vs Flask vs Pyramid: 如何去选择一个Python Web框架
2014-11-19 15:18
1176 查看
Djangovs Flask vs Pyramid: 如何去选择一个PythonWeb框架
原文链接:https://www.airpair.com/python/posts/django-flask-pyramid
我们将使用这三款框架去构建同样一个应用并且对比代码,体现出每种框架的优势和劣势。如果你想直接看代码,请点击https://github.com/ryansb/wut4lunch_demos
Flask是一个“微型”框架,主要关注一些简单的应用。Pyramid和Django都是关注大型应用的框架,但是使用不同的方法来达到不同的扩展性和灵活性。Pyramid关注灵活性,让开发者为自己的项目自主选择合适的工具。这意味着开发者可以选择数据库、URL架构、模板风格等等。Django注重将一个web应用所需的所有模块都包括进来,开发者只需要直接使用该框架进行工作即可。
Django默认自带ORM,而Pyramid和Flask让开发者自行去选择如何存储数据。非Django的web应用最常使用的ORM是SQLAlchemy。当然还有其他众多的选择,如DynamoDB和MongoDB、LevelDB、SQLite等。
Flask,三个框架中最年轻的一个,始于2010年中。Pyramid框架出自Pylons,在2010年末得名,最早的一个版本是在2005年。Django在2006年发布第一个版本,就在Pylons刚开始的时候。Pyramid和Django都是非常成熟的框架,有相当多的插件和扩展模块来满足各类需求。
虽然Flask更年轻一些,但其更有机会去学习之前的框架并把自己的关注点放到了小项目上。其经常被只有一两个功能的小项目使用,比如httpbin,http://httpbin.org/,一个简单但是强力的调试和测试HTTP的库。
这就是Flask没有内嵌引导程序的原因了:没有这样的需求。
基于上面这个例子,这是一个已经可以运行的基于Flask的网站了。因此,甚至一个没有开发过Python Web应用的开发者都可以直接开始开发了。
对于那些不同功能组件 需要分割的项目,Flask有blueprints机制。例如,你可以将所有用户相关的功能放在users.py文件中,所有销售相关的功能放在ecommerce.py中,然后将他们导入到site.py中。这里我们不再举例说明了,超出了这个实例程序讨论的范围。
Pyramid 通常被用来开发比Flask更大型的应用。因此,pcreate创建的项目有着更多的内容,包括基本的配置文件、模板示例和需要将你的项目上传到Python Package Index所需要的文件。
我们已经可以明显地看出Django和Pyramid的不同之处了。Django将不同的项目划分到不同的应用中去。而Flask和Pyramid会多个应用放到一个项目中去,通过不同的view来进行区分。当然,开发者手动地进行区分也是可行的,但是默认并不进行区分。
Django默认只提供空的model和模板文件,新用户只能看到一些简单的示例代码。
引导程序不引导用户去打包他们的应用,这种做法有一个不足之处,是新手没有这个意识去这样做。如果一个开发者之前没有打包过应用,那么他会发现他第一次部署的时候会有多么的困难。但基本上小型的项目都没有统一打包。
模板让你能够动态地更改页面信息,而不要调用AJAX。这个机制从用户的角度来说非常的友好,因为你只需要取一次全页面的信息和其他动态的数据,对于一些移动设备访问网站来说,这样的行为能为他们节省许多时间。
所有的模板都基于context,提供动态的信息给模板并最终渲染到HTML中。让我们来看一个例子,将用户的登录名显示给他们看。
接下来我们需要将user对象传入到模板中去。可以在其中直接访问其fullname属性。
首先,你会发现其中{% if user %}这个结构。在Django中{%是用来放循环或条件控制等语句的。if user用来判断是否有user传入。匿名user是无法看到’You are logged in as xxx’的页面的。
在if代码块中,只需要简单地把对象及其属性放到{{ }}中去即可,模板就会自动去调用实际的值。
另一个模板的常见用法是显示成组的信息,比如商业网站的库存信息:
其中,我们仍然可以使用{%来循环遍历仓库中所有的项目并且填充到各自的页面中,如:
对于大部分的需求来说,Django的模板系统可以通过非常简单的结构来满足。
Jinja2和Django的模板系统偶读提供了filtering功能。一个list在被显示之前可以被一个指定的函数进行处理。例如:
Jinja2的模板语言中,能够传递任意数量的参数给filter,因为Jinja2进行的是函数的调用,将参数传递给filter之后的函数。Django使用一个冒号作为filter和其参数的分隔符,这导致了参数的数量被限制在了1个,因为只能有一个冒号,冒号后面的内容都被认作为是参数。
Jinja2和Django的模板系统对于for循环都是类似的,让我们来看看他们的区别在哪里。在Jinja2中,附带了for-else-endfor架构,让你能够遍历list,并且在没有内容的情况下进入else进行处理。
Django也有类似的结构,但是关键字是empty。如:
除了上面提到的各类区别,Jinja2提供了更多的控制或功能。比如其安全性和提前编译模板以避免语法错误等功能,使其面对Django更优一筹。
但是模板的写法就非常不一样了。ZPT(Zope Page Template)是一个基于XML的模板标准,所有我们使用XSLT类似的语法:
Chameleon实际上使用三个不同的命名空间来进行模板内的操作。TAL(template attribute language)提供了基本的条件判断、字符串格式化和填充tag内容等操作。上面的例子就是使用了tal来进行填充。对于更高级的用法,我们就需要使用到TALES和METAL。TALES(Template Attribute Language Expression Syntax)提供了高级字符串处理的表达式和Python表达式求值、表达式导入和模板等。
METAL(Macro Expansion Template Attribute Language)是最强大也是最复杂的部分。其是可扩展的。
接下来是model模块,基本上类似
是不是很简单?最困难的部分就是找到正确的SQLAlchemy data类型和长度。
构建提交的表单也是很简单的。导入Flask-WTForms和正确的field类型,你就会发现表单看上去非常像我们的model,主要的区别一个新的提交按钮和输入框的命名。
其中SECRET_KEY这个字段被WTForms用来建立CSRF令牌等其他用途。
接下来在模板中把表单加进去:
在这段代码中,我们通过Lunch.query.all()获取到所有已经上传的午餐信息,并且初始化了一个表单供用户上传他们自己的数据。接下来是模板的内容:
首先是开头的介绍:
接着是最重要的部分,将我们查询的结果通过循环遍历出来,全部呈现到页面上:
<form>中明显可以看出,当用户POST一个表单的时候,会转入/new指明的模块进行处理:
确认提交上来的数据正确无误之后,就会将其存储到数据库中。以供后续操作查阅。
<
c6b0
pre name="code" class="python">if __name__ == "__main__":
db.create_all()
# make our sqlalchemy tables
app.run()
最终我们建立数据库并启动我们的app。 代码量非常的少!!
对于表单系统,Django有自己的一套,和Flask的比起来,只是语法上略有不同。
接下来我们需要创建一个LunchForm的实例并将其传递给模板。
render函数是Django中用来处理request、模板路径和内容的,类似于Flask中的render_template。
将用户上传的数据保存到数据库,Django并未采用直接调用数据库session的方法,而是使用了框架自带的.save()方法。非常的整洁!
我们还需要告诉Django-admin我们的model在哪里:
接下来是我们的页面信息:
值得一提的是,Django有一个非常方便的途径在页面中加入其他的视图。url标签让你能够定义APP的URL而不需要破坏视图。例如:
然后我们还需要包含{% csrf_token%}来确保CSRF正常。但这些都是小问题。
表单是这样的:
关于表单的渲染也比Django要复杂一些。首先我们需要定义表单,同时渲染主页:
数据库查询语句的语法和Flask都是类似的,因为两者都用了SQLAlchemy ORM来提供持久性存储。Pyramid中可以直接返回模板的context dictionary,而不用调用render函数。@view_config装饰器自动将返回的context传递给模板进行渲染。
表单数据是非常容易可以得到的,因为Pyramid自动将表单数据解析成一个字典供我们调用。ZopeTransactions模块保证了在多用户并发存储的情况下,不同的线程之间不会互相干扰。这也是一个值得一提的地方。
目前为止最受欢迎的框架是Django,其大型应用例如:Bitbucket、Pinterest、Instagram和Onion。对于大多数需求,Django默认的解决方案都是非常明智的,因此其也非常适用于中到大型的web应用开发。
Flask对于那些希望用Python进行web开发同时开发的项目规模很小功能很简单的开发者而言,是不二的选择。其提供了很多简单的接口和工具供开发者使用,且开发出来的代码量非常小,配置文件的大小也非常小。
这篇文章中提到的区别之处,并不仅仅是表面上看到的那样可能只是些语法上的区别,更多地会影响到整个产品的设计和项目交付的速度。对于我们的示例程序,功能简单,因此Flask就能胜任。Django就会感到笨重。Pyramid的灵活性也没有体现出来。但是在实际的工作中,需求往往是一个接一个来且不断变化的,这时候希望你能想起来到底哪个才是最适合你的!
原文链接:https://www.airpair.com/python/posts/django-flask-pyramid
1 前言
Pyramid,Django和Flask都是非常不错的Web框架,如何为你的项目从中选择最合适的是一个问题。本文中,会使用这三个Web框架来实现具备同一个功能的网站,以此来进行对比。2 简介
PythonWeb框架的世界里总是充满着选择,Django,Flask,Pyramid,Tornado,Bottle,Diesel,Pecan,Falcon和其他各式各样的框架摆在开发者的眼前。作为一个开发者,你需要能够从中选出一款适合你的能帮助你完成项目的框架。本文中,我们把注意力集中到Flask,Pyramid和Django上。我们将使用这三款框架去构建同样一个应用并且对比代码,体现出每种框架的优势和劣势。如果你想直接看代码,请点击https://github.com/ryansb/wut4lunch_demos
Flask是一个“微型”框架,主要关注一些简单的应用。Pyramid和Django都是关注大型应用的框架,但是使用不同的方法来达到不同的扩展性和灵活性。Pyramid关注灵活性,让开发者为自己的项目自主选择合适的工具。这意味着开发者可以选择数据库、URL架构、模板风格等等。Django注重将一个web应用所需的所有模块都包括进来,开发者只需要直接使用该框架进行工作即可。
Django默认自带ORM,而Pyramid和Flask让开发者自行去选择如何存储数据。非Django的web应用最常使用的ORM是SQLAlchemy。当然还有其他众多的选择,如DynamoDB和MongoDB、LevelDB、SQLite等。
3 关于框架
Django自带所有所需模块的模式使得开发者能够非常容易地直接关注web应用开发本身,而不需要去做很多关于应用架构如何设计的决定。Django内嵌了模板、表单、路由、认证、基本数据库管理等模块。Pyramid包括路由和认证,但是模板和数据库管理则需要额外的库。Flask,三个框架中最年轻的一个,始于2010年中。Pyramid框架出自Pylons,在2010年末得名,最早的一个版本是在2005年。Django在2006年发布第一个版本,就在Pylons刚开始的时候。Pyramid和Django都是非常成熟的框架,有相当多的插件和扩展模块来满足各类需求。
虽然Flask更年轻一些,但其更有机会去学习之前的框架并把自己的关注点放到了小项目上。其经常被只有一两个功能的小项目使用,比如httpbin,http://httpbin.org/,一个简单但是强力的调试和测试HTTP的库。
4 社区
从StackOverflow上各个框架相关的问题数量就可以看出哪个框架更加受欢迎了。5 引导程序
Django和Pyramid都内嵌各自的引导程序。Flask并未内嵌的原因是其使用者并不会使用Flask去开发大型的MVC应用。
5.1 Flask
7行代码就可以组成一个基于Flask的Hello World应用。# from http://flask.pocoo.org/ tutorial from flask import Flask app = Flask(__name__) @app.route("/") # take note of this decorator syntax, it's a common pattern def hello(): return "Hello World!" if __name__ == "__main__": app.run()
这就是Flask没有内嵌引导程序的原因了:没有这样的需求。
基于上面这个例子,这是一个已经可以运行的基于Flask的网站了。因此,甚至一个没有开发过Python Web应用的开发者都可以直接开始开发了。
对于那些不同功能组件 需要分割的项目,Flask有blueprints机制。例如,你可以将所有用户相关的功能放在users.py文件中,所有销售相关的功能放在ecommerce.py中,然后将他们导入到site.py中。这里我们不再举例说明了,超出了这个实例程序讨论的范围。
5.2 Pyramid
Pyramid的引导程序叫做pcreate,是Pyramid的组成部分。$ pcreate-s starter hello_pyramid # Just make a Pyramid project
Pyramid 通常被用来开发比Flask更大型的应用。因此,pcreate创建的项目有着更多的内容,包括基本的配置文件、模板示例和需要将你的项目上传到Python Package Index所需要的文件。
hello_pyramid ├── CHANGES.txt ├── development.ini ├── MANIFEST.in ├── production.ini ├── hello_pyramid │ ├── __init__.py │ ├── static │ │ ├── pyramid-16x16.png │ │ ├── pyramid.png │ │ ├── theme.css │ │ └── theme.min.css │ ├── templates │ │ └── mytemplate.pt │ ├── tests.py │ └── views.py ├── README.txt └── setup.py
5.3 Django
Django也有自带的引导程序———django-admin。django-admin startproject hello_django django-admin startapp howdy # make an application within our project
我们已经可以明显地看出Django和Pyramid的不同之处了。Django将不同的项目划分到不同的应用中去。而Flask和Pyramid会多个应用放到一个项目中去,通过不同的view来进行区分。当然,开发者手动地进行区分也是可行的,但是默认并不进行区分。
hello_django ├── hello_django │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── howdy │ ├── admin.py │ ├── __init__.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py └── manage.py
Django默认只提供空的model和模板文件,新用户只能看到一些简单的示例代码。
引导程序不引导用户去打包他们的应用,这种做法有一个不足之处,是新手没有这个意识去这样做。如果一个开发者之前没有打包过应用,那么他会发现他第一次部署的时候会有多么的困难。但基本上小型的项目都没有统一打包。
6 模板
有了基本的HTTP 服务器还远远不够,用户肯定希望你还能有个风光靓丽的界面。模板让你能够动态地更改页面信息,而不要调用AJAX。这个机制从用户的角度来说非常的友好,因为你只需要取一次全页面的信息和其他动态的数据,对于一些移动设备访问网站来说,这样的行为能为他们节省许多时间。
所有的模板都基于context,提供动态的信息给模板并最终渲染到HTML中。让我们来看一个例子,将用户的登录名显示给他们看。
6.1 Django
我们的示例非常简单,假设我们有一个user对象,其有一个fullname属性,包含了user的名字。我们会这样传递给模板:def a_view(request): # get the logged in user # ... do more things return render_to_response( "view.html", {"user": cur_user} )
接下来我们需要将user对象传入到模板中去。可以在其中直接访问其fullname属性。
<!-- view.html --> <div class="top-bar row"> <div class="col-md-10"> <!-- more top bar things go here --> </div> {% if user %} <div class="col-md-2 whoami"> You are logged in as {{ user.fullname }} </div> {% endif %} </div>
首先,你会发现其中{% if user %}这个结构。在Django中{%是用来放循环或条件控制等语句的。if user用来判断是否有user传入。匿名user是无法看到’You are logged in as xxx’的页面的。
在if代码块中,只需要简单地把对象及其属性放到{{ }}中去即可,模板就会自动去调用实际的值。
另一个模板的常见用法是显示成组的信息,比如商业网站的库存信息:
def browse_shop(request): # get items return render_to_response( "browse.html", {"inventory": all_items} )
其中,我们仍然可以使用{%来循环遍历仓库中所有的项目并且填充到各自的页面中,如:
{% for widget in inventory %} <li><a href="/widget/{{ widget.slug }}/">{{ widget.displayname }}</a></li> {% endfor %}
对于大部分的需求来说,Django的模板系统可以通过非常简单的结构来满足。
6.2 Flask
Flask默认使用Django推荐的Jinja2模板语言,但是也可以配置成使用其他的语言。实际上Jinja2和Django的模板系统还是有一些不同之处的,Jinja2更加易读。Jinja2和Django的模板系统偶读提供了filtering功能。一个list在被显示之前可以被一个指定的函数进行处理。例如:
<!-- Django --> <div class="categories">Categories: {{ post.categories|join:", " }}</div> <!-- now in Jinja --> <div class="categories">Categories: {{ post.categories|join(", ") }}</div>
Jinja2的模板语言中,能够传递任意数量的参数给filter,因为Jinja2进行的是函数的调用,将参数传递给filter之后的函数。Django使用一个冒号作为filter和其参数的分隔符,这导致了参数的数量被限制在了1个,因为只能有一个冒号,冒号后面的内容都被认作为是参数。
Jinja2和Django的模板系统对于for循环都是类似的,让我们来看看他们的区别在哪里。在Jinja2中,附带了for-else-endfor架构,让你能够遍历list,并且在没有内容的情况下进入else进行处理。
{% for item in inventory %} <div class="display-item">{{ item.render() }}</div> {% else %} <div class="display-warn"> <h3>No items found</h3> <p>Try another search, maybe?</p> </div> {% endfor %}
Django也有类似的结构,但是关键字是empty。如:
{% for item in inventory %} <div class="display-item">{{ item.render }}</div> {% empty %} <div class="display-warn"> <h3>No items found</h3> <p>Try another search, maybe?</p> </div> {% endfor %}
除了上面提到的各类区别,Jinja2提供了更多的控制或功能。比如其安全性和提前编译模板以避免语法错误等功能,使其面对Django更优一筹。
6.3 Pyramid
Pyramid也支持很多模板语言(如Jinja2或Mako),但是其使用Chameleon作为默认的模板系统。我们来看看前面提到的显示username的例子在Pyramid里是如何实现的,Python 代码看上去比较类似:@view_config(renderer='templates/home.pt') def my_view(request): # do stuff... return {'user': user}
但是模板的写法就非常不一样了。ZPT(Zope Page Template)是一个基于XML的模板标准,所有我们使用XSLT类似的语法:
<div class="top-bar row"> <div class="col-md-10"> <!-- more top bar things go here --> </div> <div tal:condition="user" tal:content="string:You are logged in as ${user.fullname}" class="col-md-2 whoami"> </div> </div>
Chameleon实际上使用三个不同的命名空间来进行模板内的操作。TAL(template attribute language)提供了基本的条件判断、字符串格式化和填充tag内容等操作。上面的例子就是使用了tal来进行填充。对于更高级的用法,我们就需要使用到TALES和METAL。TALES(Template Attribute Language Expression Syntax)提供了高级字符串处理的表达式和Python表达式求值、表达式导入和模板等。
METAL(Macro Expansion Template Attribute Language)是最强大也是最复杂的部分。其是可扩展的。
7 各个框架的实例展示
下面我们来创建一个APP叫做wut4lunch,用来告诉别人你午饭吃了什么。这个APP允许用户上传他们午餐吃了什么,然后浏览别人吃的什么,预期主页面是这个样子的:7.1 Flask
代码非常简单,主要包括初始化APP和从ORM获取信息。from flask import Flask # For this example we'll use SQLAlchemy, a popular ORM that supports a # variety of backends including SQLite, MySQL, and PostgreSQL from flask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__) # We'll just use SQLite here so we don't need an external database app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db' db = SQLAlchemy(app)
接下来是model模块,基本上类似
class Lunch(db.Model): """A single lunch""" id = db.Column(db.Integer, primary_key=True) submitter = db.Column(db.String(63)) food = db.Column(db.String(255))
是不是很简单?最困难的部分就是找到正确的SQLAlchemy data类型和长度。
构建提交的表单也是很简单的。导入Flask-WTForms和正确的field类型,你就会发现表单看上去非常像我们的model,主要的区别一个新的提交按钮和输入框的命名。
其中SECRET_KEY这个字段被WTForms用来建立CSRF令牌等其他用途。
from flask.ext.wtf import Form from wtforms.fields import StringField, SubmitField app.config['SECRET_KEY'] = 'please, tell nobody' class LunchForm(Form): submitter = StringField(u'Hi, my name is') food = StringField(u'and I ate') # submit button will read "share my lunch!" submit = SubmitField(u'share my lunch!')
接下来在模板中把表单加进去:
from flask import render_template @app.route("/") def root(): lunches = Lunch.query.all() form = LunchForm() return render_template('index.html', form=form, lunches=lunches)
在这段代码中,我们通过Lunch.query.all()获取到所有已经上传的午餐信息,并且初始化了一个表单供用户上传他们自己的数据。接下来是模板的内容:
首先是开头的介绍:
<html> <title>Wut 4 Lunch</title> <b>What are people eating?</b> <p>Wut4Lunch is the latest social network where you can tell all your friends about your noontime repast!</p>
接着是最重要的部分,将我们查询的结果通过循环遍历出来,全部呈现到页面上:
<li><strong>{{ lunch.submitter|safe }}</strong> just ate <strong>{{ lunch.food|safe }}</strong> {% else %} <li><em>Nobody has eaten lunch, you must all be starving!</em></li> {% endfor %} </ul> <b>What are YOU eating?</b> <form method="POST" action="/new"> {{ form.hidden_tag() }} {{ form.submitter.label }} {{ form.submitter(size=40) }} <br/> {{ form.food.label }} {{ form.food(size=50) }} <br/> {{ form.submit }} </form> </html>
<form>中明显可以看出,当用户POST一个表单的时候,会转入/new指明的模块进行处理:
from flask import url_for, redirect @app.route(u'/new', methods=[u'POST']) def newlunch(): form = LunchForm() if form.validate_on_submit(): lunch = Lunch() form.populate_obj(lunch) db.session.add(lunch) db.session.commit() return redirect(url_for('root'))
确认提交上来的数据正确无误之后,就会将其存储到数据库中。以供后续操作查阅。
<
c6b0
pre name="code" class="python">if __name__ == "__main__":
db.create_all()
# make our sqlalchemy tables
app.run()
最终我们建立数据库并启动我们的app。 代码量非常的少!!
7.2 Django
Django的版本和Flask版本非常类似,但是其分散在不同的文件中。让我们先看最类似的部分:数据库的model。# from wut4lunch/models.py from django.db import models class Lunch(models.Model): submitter = models.CharField(max_length=63) food = models.CharField(max_length=255)
对于表单系统,Django有自己的一套,和Flask的比起来,只是语法上略有不同。
from django import forms from django.http import HttpResponse from django.shortcuts import render, redirect from .models import Lunch # Create your views here. class LunchForm(forms.Form): """Form object. Looks a lot like the WTForms Flask example""" submitter = forms.CharField(label='Your name') food = forms.CharField(label='What did you eat?')
接下来我们需要创建一个LunchForm的实例并将其传递给模板。
lunch_form = LunchForm(auto_id=False) def index(request): lunches = Lunch.objects.all() return render( request, 'wut4lunch/index.html', { 'lunches': lunches, 'form': lunch_form, } )
render函数是Django中用来处理request、模板路径和内容的,类似于Flask中的render_template。
def newlunch(request): l = Lunch() l.submitter = request.POST['submitter'] l.food = request.POST['food'] l.save() return redirect('home')
将用户上传的数据保存到数据库,Django并未采用直接调用数据库session的方法,而是使用了框架自带的.save()方法。非常的整洁!
我们还需要告诉Django-admin我们的model在哪里:
from wut4lunch.models import Lunch admin.site.register(Lunch)
接下来是我们的页面信息:
<ul> {% for lunch in lunches %} <li><strong>{{ lunch.submitter }}</strong> just ate <strong>{{ lunch.food }}</strong></li> {% empty %} <em>Nobody has eaten lunch, you must all be starving!</em> {% endfor %} </ul>
值得一提的是,Django有一个非常方便的途径在页面中加入其他的视图。url标签让你能够定义APP的URL而不需要破坏视图。例如:
<form action="{% url 'newlunch' %}" method="post"> {% csrf_token %} {{ form.as_ul }} <input type="submit" value="I ate this!" /> </form>
然后我们还需要包含{% csrf_token%}来确保CSRF正常。但这些都是小问题。
7.3 Pyramid
最后让我们看一看同样的功能,用Pyramid是如何实现的。和前两个最大的区别在于模板。Chameleon模板的语法严格遵循XSLT。<!-- pyramid_wut4lunch/templates/index.pt --> <div tal:condition="lunches"> <ul> <div tal:repeat="lunch lunches" tal:omit-tag=""> <li tal:content="string:${lunch.submitter} just ate ${lunch.food}"/> </div> </ul> </div> <div tal:condition="not:lunches"> <em>Nobody has eaten lunch, you must all be starving!</em> </div>
表单是这样的:
<pre name="code" class="html"><b>What are YOU eating?</b> <form method="POST" action="/newlunch"> Name: ${form.text("submitter", size=40)} <br/> What did you eat? ${form.text("food", size=40)} <br/> <input type="submit" value="I ate this!" /> </form> </html>
关于表单的渲染也比Django要复杂一些。首先我们需要定义表单,同时渲染主页:
# pyramid_wut4lunch/views.py class LunchSchema(Schema): submitter = validators.UnicodeString() food = validators.UnicodeString() @view_config(route_name='home', renderer='templates/index.pt') def home(request): lunches = DBSession.query(Lunch).all() form = Form(request, schema=LunchSchema()) return {'lunches': lunches, 'form': FormRenderer(form)}
数据库查询语句的语法和Flask都是类似的,因为两者都用了SQLAlchemy ORM来提供持久性存储。Pyramid中可以直接返回模板的context dictionary,而不用调用render函数。@view_config装饰器自动将返回的context传递给模板进行渲染。
<pre name="code" class="python">@view_config(route_name='newlunch', renderer='templates/index.pt', request_method='POST') def newlunch(request): l = Lunch( submitter=request.POST.get('submitter', 'nobody'), food=request.POST.get('food', 'nothing'), ) with transaction.manager: DBSession.add(l) raise exc.HTTPSeeOther('/')
表单数据是非常容易可以得到的,因为Pyramid自动将表单数据解析成一个字典供我们调用。ZopeTransactions模块保证了在多用户并发存储的情况下,不同的线程之间不会互相干扰。这也是一个值得一提的地方。
8 总结
Pyramid是三个框架中最灵活的。可以用作类似我们举的例子这种小应用,也可以大到Dropbox这类大型网站。Fedora开源社区选择Pyramid作为他们社区badges system的开发框架。最多的关于Pyramid的抱怨就是使用它的选择太多了,以至于想要新写一个项目必须要先确定好如何去实现。目前为止最受欢迎的框架是Django,其大型应用例如:Bitbucket、Pinterest、Instagram和Onion。对于大多数需求,Django默认的解决方案都是非常明智的,因此其也非常适用于中到大型的web应用开发。
Flask对于那些希望用Python进行web开发同时开发的项目规模很小功能很简单的开发者而言,是不二的选择。其提供了很多简单的接口和工具供开发者使用,且开发出来的代码量非常小,配置文件的大小也非常小。
这篇文章中提到的区别之处,并不仅仅是表面上看到的那样可能只是些语法上的区别,更多地会影响到整个产品的设计和项目交付的速度。对于我们的示例程序,功能简单,因此Flask就能胜任。Django就会感到笨重。Pyramid的灵活性也没有体现出来。但是在实际的工作中,需求往往是一个接一个来且不断变化的,这时候希望你能想起来到底哪个才是最适合你的!
8.1 鸣谢
感谢很多对这篇文章做出贡献的人!!(具体人名请参照原文!^_^)相关文章推荐
- 选择一个 Python Web 框架:Django vs Flask vs Pyramid
- [Link]选择一个 Python Web 框架:Django vs Flask vs Pyramid
- Django vs Flask vs Pyramid 选择你的WEB框架
- 技术文章 | Python Web框架:Django vs Flask vs Pyramid
- [转]Django 是一个 Python 下的 web 开发框架[学习资料]
- python常用web框架简单性能测试结果分享(包含django、flask、bottle、tornado)
- (转)Django vs Flask vs Pyramid: Choosing a Python Web Framework
- Python web框架Django学习(1)——在win7 64bit下配置开发环境Django:一个可以使Web开发工作愉快并且高效的Web开发框架。 使用Django,使你能够以最小的代价构建和
- Python实现手写一个类似django的web框架示例
- Python微型web开发框架flask介绍及一个小例子
- python常用web框架性能测试(django,flask,bottle,tornado)
- Flask 一个Python的微型WEB开发框架
- python常用web框架简单性能测试结果分享(包含django、flask、bottle、tornado)
- 如何选择一个优秀的Web开发框架?
- python常用web框架性能测试(django,flask,bottle,tornado)
- Python Web 框架,第 1 部分: 使用 Django 和 Python 开发 Web 站点
- python下的web开发框架-Django,创建项目
- 如何选择最为合适的Web开发框架(转)
- 介绍两个Python web框架:Django & Tornado
- 用 Python 开发 Web 站点的两个开源框架 Django 和 TurboGears