TL;DR: Pyramid, Django, and Flask are all excellent frameworks, and choosing just one for a project is hard. We'll see working apps with identical functionality in all three frameworks to make comparing the three easier. Skip to Frameworks in Action[1]1 Introduction
The world of Python web frameworks is full of choices. Django, Flask, Pyramid, Tornado, Bottle, Diesel, Pecan, Falcon, and many more are competing for developer mindshare. As a developer you want to cut the legions of options down to the one that will help you finish your project and get on to the Next Big Thing (tm). We'll focus on Flask, Pyramid, and Django. Their ideal cases span from micro-project to enterprise-size web service.
To help make the choice between the three easier (or at least more informed), we'll build the same application in each framework and compare the code, highlighting the strengths and weaknesses of each approach. If you just want the code, skip straight to Frameworks in Action or view the code on Github.
Flask is a "microframework" primarily aimed at small applications with simpler requirements. Pyramid and Django are both aimed at larger applications, but take different approaches to extensibility and flexibility. Pyramid targets flexibility and lets the developer use the right tools for their project. This means the developer can choose the database, URL structure, templating style, and more. Django aims to include all the batteries a web application will need so developers need only open the box and start working, pulling in Django's many modules as they go.
Django includes an ORM out of the box, while Pyramid and Flask leave it to the developer to choose how (or if) they want their data stored. The most popular ORM for non-Django web applications is SQLAlchemy by far, but there are plenty of other options from DynamoDB and MongoDB to simple local persistence like LevelDB or plain SQLite. Pyramid is designed to use any persistence layer, even yet-to-be-invented ones.
2 About the Frameworks
Django's "batteries included" approach makes it easy for developers who know Python already to dive in to web applications quickly without needing to make a lot of decisions about their application's infrastructure ahead of time. Django has for templating, forms, routing, authentication, basic database administration, and more built in. In contrast, Pyramid includes routing and authentication, but templating and database administration require external libraries.
The extra work up front to choose components for Flask and Pyramid apps yields more flexibility for developers whose use case doesn't fit a standard ORM, or who need to interoperate with different workflows or templating systems.
Flask, the youngest of the three frameworks, started in mid-2010. The Pyramid framework began life in the Pylons project and got the name Pyramid in late 2010, though the first release was in 2005. Django had its first release in 2006, shortly after the Pylons (eventually Pyramid) project began. Pyramid and Django are extremely mature frameworks, and have accumulated plugins and extensions to meet an incredibly large range of needs.
Though Flask has a shorter history, it has been able to learn from frameworks that have come before and has set its sights firmly on small projects. It is clearly used most often in smaller projects with just one or two functions. One such project is httpbin, a simple (but extremely powerful) helper for debugging and testing HTTP libraries.
3 Community
The prize for most active community goes to Django with 80,000 StackOverflow questions and a healthy set of blogs from developers and power users. The Flask and Pyramid communities aren't as large, but their communities are quite active on their mailing lists and on IRC. With only 5,000 StackOverflow questions tagged, Flask is 15x smaller than Django. On Github, they have a nearly identical number of stars with 11,300 for Django, and 10,900 for Flask.
All three frameworks are available under BSD-derived permissive licenses. Both Flask's and Django's licenses are 3-clause BSD, while Pyramid's Repoze Public License RPL is a derivative of the 4-clause BSD license.
4 Bootstrapping
Django and Pyramid both come with bootstrapping tools built in. Flask includes nothing of the sort because Flask's target audience isn't trying to build large MVC applications.
4.1 Flask
Flask's Hello World app has to be the simplest out there, clocking in at a puny 7 lines of code in a single Python file.
- # 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()
For projects that need more separation between components, Flask has blueprints. For example, you could structure your Flask app with all user-related functions in users.py and your sales-related functions in ecommerce.py, then import them and add them to your app in site.py. We won't go over this functionality, as it's beyond the needs of our demo app.
4.2 Pyramid
Pyramid's bootstrapping tool is called pcreate which is part of Pyramid. Previously the Paste suite of tools provided bootstrapping for but has since been replaced with a Pyramid-specific toolchain.
- $ pcreate -s starter hello_pyramid # Just make a Pyramid project
- 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
4.3 Django
Django also has its own bootstrapping tool built in as a part of django-admin.
- django-admin startproject hello_django
- django-admin startapp howdy # make an application within our project
- 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
The downside of the bootstrap tool not guiding users to package their apps is that novice users won't. If a developer hasn't packaged an app before, they'll find themselves rudely surprised upon their first deploy. Projects with a large community like django-oscar are packaged and available on PyPi, but smaller projects on Github often to lack uniform packaging.
5 Templating
Just having a Python application that can respond to HTTP requests is a great start, but it's a good bet that most of your users won't be interested in using curl to interact with your web app. Fortunately, all three contenders provide an easy way to fill in HTML with custom info, and let folks enjoy your swanky Bootstrap frontend.
Templating lets you inject dynamic information directly into your page without using making AJAX requests. This is nice from a user experience perspective since you only need to make one round-trip to get the full page and all its dynamic data. This is especially important on mobile sites where round trips can take multiple seconds.
All the templating options we'll see rely on a "context" that provides the dynamic information for the template to render into HTML. The simplest use case for a template would be to populate a logged-in user's name to greet them properly. It would be possible to use AJAX to get this sort of dynamic information, but requiring a whole call just to fill in a user's name would be a bit excessive when templates are this easy.
5.1 Django
Our example use case is about as easy as it gets, assuming that we have a user object that has a fullname property containing a user's name. In Python we'd pass the current user to the template like so:
- def a_view(request):
- # get the logged in user
- # ... do more things
- return render_to_response(
- "view.html",
- {"user": cur_user}
- )
- <!-- 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>
Inside the if block, you can see that including the name is as simple as wrapping the property we want to insert in {{ }}. The {{ is used to insert actual values into the template, such as {{ user.fullname }}.
Another common use for templates is displaying groups of things, like the inventory page for an ecommerce site.
- 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 %}
Written by Ryan Brown (continue)
If you found this post interesting, follow and support us.
Suggest for you:
No comments:
Post a Comment