
Ask HN: Best Python web framework - benohear
I know this question gets asked every now and again, but the most recent informed thread I found was two years old and, as we all know, things move on.<p>Last time, the answer could be summarized as "Django but ...", with Pylons and Flask getting a good mention. Have these now "overtaken" the incumbent? What about Web2Py?
======
idan
(Full disclosure: I'm a member of Django's core team)

There's no single "best" for every application. One-size-fits-none. One of
Django's strengths is in the fact that parts of the framework come off easily
when they no longer serve your needs. If the ORM is no longer working for you,
you can use SQLAlchemy or write raw SQL. Authentication no longer working for
you? Write your own or use a 3rd party one.

Et cetera. The key aspect is that you don't need to sacrifice the entire
framework when only one part of it no longer addresses your needs. Keep in
mind that 99% of sites never even reach this point.

The other major strength of django is the rich ecosystem of 3rd party apps.
That's a lot of code you don't need to write yourself.

That being said, Flask is popular for a reason. Django offers a lot of power,
which means adding some complexity to even the simplest projects (something
we're working to address with features like project templates in Django 1.4).
Flask fills a niche for a framework that is easy to get up and running and
addresses 90% of the things which 90% of people need for many projects.

I've heard good things about pyramid, but haven't had a chance to play yet.

I haven't had the "pleasure" of working with web2py, and I'm not knocking the
effort which Massimo puts into it, but the choices made there often elicit a
raised eyebrow. Ignoring my opinion for a moment, the smartest web hackers I
know universally regard web2py as a fundamentally incorrect way to approach
web development—but usually say so in far more colorful terms.

TL;DR

* Flask for simpler stuff

* Django for anything larger, or simple stuff that leverages a 3rd-party app you need.

* What matters is the app you ship, not the framework it was built with.

* Django developers are in super-high demand. I get cold-called frequently.

~~~
buro9
I would simplify further:

Are you building an API? If yes, use Flask.

Are you building a website? If yes, use Django.

Are you building an API and a website? If yes, use Flask for the API and
consume it from a Django site.

I wouldn't advocate using Django but ditching the ORM for SQLAlchemy, nor
replacing the Auth, as noted (above or below my comment) it gets messy and
becomes a lonely road fast.

I would advocate moving a lot (all?) of the model into a REST API, implemented
in Flask, using SQLAlchemy. But perhaps my experience isn't as wide or deep as
others.

~~~
simonw
I disagree on one point there... if you're building both an API and a website,
there's no reason at all to use both Flask and Django. I can't imagine that
the benefits would outweigh the disadvantages of having to deal with two
frameworks instead of one.

I'd also argue in favour of ditching Django's auth. It's fine if your project
has very simple auth requirements, but these days very few interesting
projects have simple auth requirements - plus it's much easier to extend the
functionality of your own Account models than to try and hook extra stuff on
to Django's.

~~~
buro9
> I can't imagine that the benefits would outweigh the disadvantages of having
> to deal with two frameworks instead of one.

Separation of concerns, loose coupling.

I tended to find (in the few Django projects I worked on), that models were
frequently accessed outside the app that created and owned the model. The
subsequent dependency diagram would be spaghetti.

We had apps for each significant feature area, and when we wanted to drop a
feature it was my desire to just remove an app.

It may well have been our implementation that was the problem (poorly
separated concerns across apps), but we made great strides at solving these
problems by using APIs to both force the de-coupling and to increase our
confidence that our mobile clients (using the API) had the same capabilities
available to them as the website (because no Django dev could cheat and make a
call without the API existing).

Why Flask and not just Django again? That came down to personal preference
over how clean it is to handle headers correctly (Accept headers, CORS and
other things were fun), layout of the code and project, simplicity of testing,
etc.

Mostly it was just subjective and personal preference, once we saw that the
Django projects we had tended not to follow loose coupling, we used APIs as a
way to increase our own discipline. Preferring that the architecture helped
ensure the way we wanted to work on (and maintain) the code.

Auth we had already externalised (into the edge of the network, implemented
within Varnish, similar to Flickr's GodAuth).

~~~
clarkevans
How do you handle "foreign key references" between modules in your new
approach (using APIs to decouple?).

~~~
buro9
That's one of the fun issues with service oriented architecture.

You either choose high-chatter and low complexity, or low-chatter and high
complexity. As high-chatter is also a decrease in performance (mostly due to
JSON serialisation/deserialisation and HTTP requests), we opted for low-
chatter.

Resources that were a composite of other resources had their own knowledge of
how they were composed, and generated their own IDs to save that knowledge.
Each new composition resource got it's own Accept header identifier as a
result.

Within that composition resource, there wasn't just knowledge of "I'm composed
of x:17 and y:3", but also knowledge of how to search across the underlying
services. This could be to call search on the underlying service if one side
of the composition was dominant in applying the filter to the dataset.

Where it was trivial, a search index belonging to the composed service was
used. And because this duplicates data from the underlying resources,
messaging was put into the underlying service to notify the composed service
of changes that affect searches.

For simplicity you can just imagine that we had some kind of table in the
composed service, with ID on each row that because the ID of the composed
resource, and that we could search that table, and that messaging magic kept
that table in sync.

We could do all of this because we owned all of the services. If we didn't,
then I imagine we would have followed a similar path to <http://ql.io/>

------
peter_l_downs
I really like bottle.py [1]. I've used it for a couple of different projects;
although not fundamentally different from web.py or flask, it seems to just
"make sense".

[1] <http://bottlepy.org/docs/stable/>

An example from their website:

    
    
        from bottle import get, post, request
    
        @get('/login') # or @route('/login')
        def login_form():
            return '''<form method="POST">
                        <input name="name"     type="text" />
                        <input name="password" type="password" />
                      </form>'''
    
        @post('/login') # or @route('/login', method='POST')
        def login_submit():
            name     = request.forms.get('name')
            password = request.forms.get('password')
            if check_login(name, password):
                return "<p>Your login was correct</p>"
            else:
                return "<p>Login failed</p>"

~~~
jtreminio
PHP guy here, don't know much about other languages, but seeing HTML mixed in
with code is usually a bad code smell. Is this type of thing common in Python?

~~~
greut
PHP is about mixing it with other stuff (hence the <?php tag). So PHP smells
by definition :-)

~~~
nobleach
JSP, ASP, CFM, Rails ERB, DJango ALL have the same exact thing. The only
difference is PHP tutorials typically have a big block at the top of the
"page" for business logic, and then intersperse logic throughout the view.

Most of these other frameworks/languages (barring CFM and old ASP) expect you
to adhere to some sort of MVC.

Saying PHP smells by default is a little less than fair. :-)

------
j2labs
Try Brubeck. It's a Python web framework built around Gevent, DictShield and
ZeroMQ. It communicates with Mongrel2, it's web server, via ZeroMQ sockets so
even the annoying design of WSGI is moved out of the way.

It converts your blocking calls to nonblocking, has no spaghetti code filled
with callback shenanigans, and can even generate a full REST API for you.

<https://github.com/j2labs/brubeck>

~~~
theonlyroot
I have used Pylons, Tornado and Brubeck in my projects over last couple of
years and I must say if you are an experienced developer in Python, brubeck is
a very good candidate. It is built for scalability in mind from day one. It is
very light weight from code perspective and has a very transparent design
which is very easy to understand to dive deeper if you need to.

~~~
j2labs
As the initial author of Brubeck, I'm very glad to hear this!

------
espeed
Flask is at about the right level of abstraction in the age of polyglot DBs
and the JS movement to put the presentation in the browser. Flask gets out of
your way and makes it easy to adapt to the changing environment without having
to hack your way out of a monolith.

Diesel (<http://diesel.io/>) has piqued my interest as of late -- it's a high-
concurrency, coroutine-based framework with Flask under the hood, by the guys
at Bump.

The next-gen Python Web frameworks will probably be non-WSGI because WSGI
doesn't support WebSockets.

One approach would be a ZeroMQ-based framework like Brubeck
(<http://brubeck.io/>) behind Mongrel2 (<http://mongrel2.org/>). But AFAIK,
WebSocket support is not yet fully baked into Mongrel2. The handshake still
needs to happen on the handler side.

------
inovica
The best for what? What do you want to do?

We have found Django to be great for throwing up a site quickly. We primarily
use Pyramid now for our more serious development as it fits more with what
we're trying to achieve. My feeling is the beauty of Python is that there are
more than one ways of doing something. Define what you want out of your
framework, try some and then see how you feel

~~~
benohear
The specific project I'm looking at is a small photo-sharing app for a
newspaper website. Functionally simple, but with some pretty intense traffic
spikes. Since it's a straightforward job I'd like to use it as an opportunity
to switch to Python, which I've been itching to do for a while (alternative
would be Symfony on PHP).

However I have a longer term concern, which is that I don't want to be
learning a new framework for every project or have legacies with the "wrong"
framework knocking around. This is why I framed the question in general terms.

~~~
asto
Some stuff I know:

Django is great for learning very fast. It has all the documentation in one
place. There's generally one way to do any one thing with Django.

Pyramid is super flexible because it's not much of a framework to begin with.
Think of it as glue to stick together a bunch of components to handle specific
parts of your app (like database ORM, cache, sessions etc) and you can use any
components that you like. Pyramid is harder to pick up than Django though
because of this reason.

Pyramid is faster than django on benchmarks I've seen on the web (but this
will hardly matter in the real world in my opinion)

Both have some big projects executed using them(Disqus is written in Django
and Reddit is written in pylons for examples)

There are a bunch of other python frameworks that I haven't used yet so I
can't tell you anything about them.

I'm currently working on something using Pyramid so if you have something
specific you want to know, I'll try and answer (I'm new to this too)

I'd recommend learning django first though. It's what you should look at if
you want a quick inroad into python web frameworks without much time spent
learning.

------
beagle3
web2py is great. Really. I'm quite sure some people are confusing web.py
(toolkit behind reddit) and web2py - I know I was a couple of years ago.

web2py is super complete, but doesn't get in your way, and doesn't require you
to learn everything up front. It's DAL is much simpler (and in my opinion,
much more effective) than an ORM -- but you don't have to use it.

Its templating system is just plain python inside {{}}, where you need to add
"pass:" to dedent if it cannot be inferred from the code, but that's it. No
need to learn a new templating system.

The community is super awesome. Starter applications like issue trackers,
minimal facebooks or twitters etc. are often posted on the mailing list inside
one short message (not as an attachment -- the whole thing is posted inside
the message text, and takes no more than two screenfuls)

Really, give web2py a try if you haven't.

~~~
masklinn
> I'm quite sure some people are confusing web.py (toolkit behind reddit) and
> web2py

Quite unlikely, they'd probably have far more praises for it if they did
confuse them.

------
AnthonyB3
Well, according to InfoWorld, web2py is the best Python framework
([http://www.infoworld.com/d/application-
development/pillars-p...](http://www.infoworld.com/d/application-
development/pillars-python-six-python-web-frameworks-compared-169442)). It
also won a 2011 Bossie Award for open source development software
([http://www.infoworld.com/d/application-
development/pillars-p...](http://www.infoworld.com/d/application-
development/pillars-python-six-python-web-frameworks-compared-169442)) and a
2012 Technology of the Year Award
([http://www.infoworld.com/slideshow/24605/infoworlds-2012-tec...](http://www.infoworld.com/slideshow/24605/infoworlds-2012-technology-
of-the-year-award-winners-183313)).

Don't listen to the naysayers about web2py -- it is rare to find one who has
actually ever used it. Meanwhile, web2py has a large, active, and steadily
growing base of _real_ users who are very happy and doing just fine producing
and maintaining web applications with it. In fact, many web2py users are
former Django users who simply find web2py more productive (see
[http://www.quora.com/What-are-the-advantages-of-web2py-
over-...](http://www.quora.com/What-are-the-advantages-of-web2py-over-
Django/answer/Anthony-Bastardi)).

Note, most of the criticisms of web2py have all the earmarks of FUD
(<http://en.wikipedia.org/wiki/Fear,_uncertainty_and_doubt>) -- lots of
references to authority and calls to stick with a perceived standard way of
doing things, but not much discussion of actual technical merits nor
presentation of any empirical evidence to back up the strong claims being made
(see [http://www.quora.com/Is-web2py-a-good-Python-web-
framework/a...](http://www.quora.com/Is-web2py-a-good-Python-web-
framework/answer/Anthony-Bastardi)). Some of the critics seem overly concerned
with the notions of "explicitness" and "magic", but not everyone shares their
concerns: <https://twitter.com/#!/zedshaw/status/80418794526351360>.

------
sontek
Pyramid is probably the best at the moment. It has a lot of power when it
comes to fine grained security utilizing access control lists and it
integrates really well with the major python libraries out there.

------
iso8859-1
CherryPy has had Python 3 support for quite a while now. Not many Python
frameworks have that. Pylons just got it, so I'd go with CherryPy. You can get
WebSocket support too, and documentation is OK.

~~~
sidman
Yep, cherrypy is my tool of choice also, very simple , very light , does the
job. I have used tornado, which i quite like also ...

~~~
illumen
I like cherrypy too! :) It's like my secret python weapon.

------
ruxkor
I'm surprised nobody mentioned brubeck (<http://brubeck.io>) until now, which
takes a completely fresh approach to concurrent handling via implicit context
switching (more on their website).

Obviously, as idan mentioned already, there is no single "best" framework, so
it really depends on the type of application you want to build whether you
should choose something like bottle/flask, django/mezzanine/pinax or
brubeck/tornado, or even twisted.

------
lucian1900
Sadly, Django is still by far the most popular. It's ok, though. You're likely
to not hate it intensely. It also has a lot of third party code available, and
a fair amount of functionality built-in.

Flask is nicer (and lets you seamlessly use SQLAlchemy, which is so much
better than Django's crappy ORM), but also tiny. It's basically just a bit of
glue between werkzeug, SQLAlchemy and Jinja2.

Pyramid has more things in it than Flask and also uses SQLAlchemy.

web2py appears both bad and unpopular to me.

~~~
AnthonyB3
> web2py appears both bad and unpopular to me.

Regarding popularity, for some time now the web2py Google Group has had more
postings than the Django group, and the web2py group membership has been
growing at a much faster rate than Django. Overall, Django is still more
widely used, but web2py is certainly popular and growing rapidly.

Regarding whether web2py is "bad", that's obviously your opinion, but it is
notable that you did not provide any argument or evidence whatsoever to
support it.

------
esonderegger
I've been using Flask for my current project and I absolutely love it.

The project is a web interface for our library's digital archives (mostly
audio and video assets, but also images and print documents). Version 1 of the
project used php and mysql for the front end with python scripts handling the
transcoding and metadata handling on the back end. For a variety of reasons
the project got bloated to the point of being unmanageable. I decided I wanted
a fresh start with a python framework and considered all the ones mentioned
here.

I went with Flask because I wanted to leave the existing database structure in
place and I wanted to err on the side of the framework doing too little
instead of too much.

As a non-programmer (my job title says "audio engineer"), Flask was simple
enough to understand, but did enough to make my life considerably easier. My
one gripe is I think Flask-Login still has room for improvement, at least in
terms of documentation. I've gotten it working good enough, but I still don't
understand how credentials are passed around my application.

I'm sure other frameworks would have also gotten me to where I needed to be,
but after working with Flask for a month or so, I'm not immediately reaching
for something else.

------
tzury
Tornado.

Built-in async operations.

Not standing in your way.

Rapid developments.

Huge community.

Simply works.

Simple, yet rich.

~~~
j2labs
Don't use Tornado unless you plan to build a full SOA. Python drivers are
blocking by default and Tornado offers no support for that, meaning Tornado
blocks if you have database calls in your code.

Use gevent. Huge community. Simply works and simply scales. And it makes all
your blocking calls nonblocking automatically. Tornado just blocks.

~~~
hogu
thats a bit of a simplification - you can definiltey use tornado as long as
you've got a tornado compatible async driver. people using mongo, postgres, or
anything with an http interface are fine. Not wanting to deal with the mental
overhead of callbacks, is the reason why I no longer want to use tornado

~~~
j2labs
There are very few Tornado compatible async drivers, so I don't believe it is
a simplification.

------
dcESC
Pylons is now called pyramid. I don't know how much it changed?

I prefer pylons above Django. Simply because it feels less like a framework.

~~~
masklinn
> I don't know how much it changed?

All of the controllers stuff was replaced with the code formerly known as
repoze.bfg

~~~
obtu
While Pyramid is Pylons' appointed successor, the code is mostly from the
repoze project, with changes to make it more familiar to Pylons users:
<http://docs.pylonsproject.org/en/latest/faq/pyramid.html>

------
glimmung
Depends on what you are developing, of course.

I picked web2py about 3 years ago, and it has worked well for me. I'm
developing CRUD apps to solve business problems with the minimum of fuss and
effort, but with the confidence that I can roll my sleeves up and exercise
more control if I need to - web2py has been a good fit for that.

------
nashad
I built a couple of web.py apps and here are my observations:

\-- Advantages --

* Minimal configuration (No configuration file, just run a single python file in the simplest case)

* Getting started is really fast

* import whatever libraries you like (PyMongo, SqlAlchemy, Mako, Beaker, etc) - No lock in

* The Web.py source is straightforward enough that you can go directly there to figure stuff out

* WSGI compatible

* No Admin interface and extra scaffolding

* Very simple URL routing interface

* Simple cookbook is available for adding basic features

\-- Disadvantages --

* Smaller community

* Not a lot of documentation or guides

* Some problems will require you to look at the source

* No built in user management/auth

* Web.py development community isn't adding new features rapidly

\--Conclusion--

Probably good for rapidly building simple web apps. It seems like the
support/infrastructure needed for a large-scale production app isn't
available. However if you are willing to build out your components it will
give you maximum flexibility for a larger app

------
drahcir
I have used web2py for the last few years and have been happy with it:

\- well designed components: DAL, SQLFORM, views, etc

\- commitment to backwards compatibility

\- works on GAE

\- helpful community (groups.google.com/group/web2py)

\- thorough documentation (web2py.com/book)

The main criticism of web2py is that its design is not 'pythonic', which is
irrelevant to me.

------
aaronsnow
Richard Jones did a nice presentation about this in August 2011, comparing 10
Python frameworks along a lot of useful metrics (perf, simplicity, size,
documentation, etc) by developing the same "hello world"-ish app in each one.
He even scored them at the end.

The slides are at [http://www.slideshare.net/r1chardj0n3s/web-microframework-
ba...](http://www.slideshare.net/r1chardj0n3s/web-microframework-battle) \--
they don't seem to be loading inline now but the PDF download still works.
Video of the talk is at <http://www.youtube.com/watch?v=AYjPIMe0BhA> .

Spoiler alert: the winner was bottle.py, by a nose.

~~~
dagw
It's worth noting that he's mainly concerned with publishing existing python
apps he's already written as simple web services, not writing a complete web
site from scratch. If you just look at the slides it's easy to miss this. This
doesn't invalidate anything he says as such, but it's worth keeping this in
mind if you're planning on doing a more complete web site.

------
zengyro
I use web2py. It struggles to get the attention that Django gets, but it has a
robust development community.

It offers a good balance between Django (which i find a little big and
unwieldy), and Flask (which I think suffers from the opposite problem).

~~~
wilsaj
What's the opposite problem?

~~~
zengyro
'suffers' probably isn't the right word.

Flask is designed under the assumption that you will most likely use third
party frameworks for stuff like database abstraction and input validation.

It's kinda neat in that regard, and if you prefer to work that way then more
power to you.

But I believe Web2py gets the balance between 'batteries included' and 'find
your own damn batteries' right.

------
kung-fu-master
Flask is best IMHO. Django is good enough.

------
gbog
As with whichever framework you choose you will have to get inside its code to
understand it, adapt to it or fix it, I would advise to choose one framework
that has code that is pleasing to read and follow very strictly conventions.
Right now my box is broken so I can't check but last I have checked Django had
a relatively good pylint score, while Flask had a seemingly slightly more
messy code base.

------
calibwam
Depends on what you want from the framework. Django is good, but for a smaller
blog, try pyblosxom, it's quite nice!

------
abdulhaq
Here's a vote for cherrypy - it handles all the http / protocol shenanigans
for you, but leaves the meaty business side entirely to you - which, as an
experienced developer, is what I want.

------
edwinyzh
I've ten years of Delphi background. I'll choose Flask, because it's simple -
I immediately learned how it works, and it's neat.

------
magnusmorton
Which (or do any) of the major Python frameworks have Python 3 support?

~~~
mhd
Pyramid, CherryPy and Tornado. Bottle does, too, but I don't know if you'd
consider it "major".

------
wyuenho
BlueberryPy author here. Allow me to plug CherryPy and my micro-framework
built on top of CherryPy called BlueberryPy.

Here's my answer on stackoverflow early last year when someone asked for a
CherryPy vs Flask comparison. I believe all the points still stand and still
represent CherryPy's strengths.

1\. Simplicity. Controller object trees more or less equal to how you would
define your URLs. 2\. Flexibility. In case you don't like how the URLs are
defined by default, you can use routes or methods to expose your URL handlers,
which are just as easy. 3\. Tools. CherryPy isn't religious about WSGI, though
it's 100% compatible with the WSGI spec, the recommended approach is to use
Tools. They are simple to make and use, and the way they are wired to the
request is a lot more efficient than WSGI, which typically a request has to
pass through whether or not that particular WSGI middleware is relevant.
(Unless you use a framework where each URL handler is a WSGI application, but
wiring up WSGI apps are still annoying). There are __LOTS __of them supplied
by default that cover most of the use cases you can think of. 4\. Plugins. For
cross-cutting concerns, engine plugins are a much more granular, well-defined,
and suitable way to deal with them as opposed to a WSGI app, which is
typically the hammer people use to hammer in every screw these days. 5\. Easy
chunked responses. You just yield a string in the controller and that's it.
Very useful for returning large documents in pieces. 6\. Full-featured request
and response objects. WebOb and CherryPy are about the only 2 frameworks that
have comparably complete implementations of them, but I'd still choose
CherryPy for the last reason: 7\. Zero dependency on other packages. You won't
bring in a dozen other libraries just to run a server. You just easy_install
or pip install cherrypy and that's it.

Its WSGI server is also the canonical choice if you need a fast and stable
pure Python WSGI server implementation. It's actually really really fast and
stable:

    
    
        http://nichol.as/benchmark-of-python-web-servers
    
    
    

Now, I've been using CherryPy for about 5 years now and am still absolutely in
love with it. I love it so much that I've decided last month to open source
the micro-framework I've built on top of CherryPy called BlueberryPy:

    
    
        https://bitbucket.org/wyuenho/blueberrypy
    

It's basically a set of additional tools and plugins for CherryPy which give
you an easier integration with SQLAlchemy, logging, Redis and Jinja2,
webassets and various other goodies. It also comes with a project skeleton
generator akin to many other frameworks out there but doesn't get in your way
with the generated source files. All that BlueberryPy asks for is a
configuration directory with a few correct YAML config files with a few keys
pointing to a few classes in your package. Documentation is a little light but
more will come soon enough as I find time to finish them up. Stay tuned :P

------
intellectronica
web.py

~~~
tonetheman
i like web.py also. not sure it is has tons of feature like the others but it
is pretty simple to develop for and just works.

------
blye_kzn
web2py : others :: python : others

web2py : dj __ __* :: python : java

------
illumen
Pyramid.

<http://en.wikipedia.org/wiki/Pyramid_%28web_framework%29>

* faster.

* better quality (100% statement coverage via unit tests)

* supports latest python.

* great documentation (including free up to date book). There's also a separate pyramid cookbook.

* simplicity. If you just see a pyramid app, you can dive right in fairly easily without learning lots of alien stuff.

* sensible defaults, and you can choose to swap out parts easily if you want (templates, ORM, etc).

* works well with other python software, doesn't bundle everything in, with NIH syndrome.

* great tools. like the web console that drops straight into a debugger when an exception happens on the page you're looking at.

The framework that starts with D is a legacy framework (doesn't even support
python3 yet).

~~~
TylerE
As an alternative viewpoint

* It's complicated

* It doesn't really do much for you (have to spend lots of effort/time/learning plumbing in all the 3rd party libs)

* Lacks sensible defaults for many things

* Documentation is rather lacking. Oh, there's tons of it, but it's rather maze-like and hard to use if you don't actually understand the system. High-level overview/cookbook type stuff is severely lacking.

~~~
kstrauser
I do agree about Pyramid's initial learning curve being a bit steep (or, at
least it was more than a year ago when I was first picking it up). Still, I
fell in love with Pyramid _because_ it didn't try to do much for me.

My previous company has a huge SQLAlchemy-based codebase with literally
hundreds of defined classes, many with hugely complex relationships (as it was
built on top of a legacy database that had accreted over many years).
Switching to a non-Alchemy backend simply wasn't an option. They also have a
large, complex web application built in Zope with hundreds of tested, working
page templates. Django is the easy first choice when starting a new Python web
app. However, if we'd replaced the Django ORM with SQLAlchemy and Django's
templates with something like ZPT so that we could incorporate our large pre-
existing code, there wouldn't have been a lot of Django we could still use. In
particular, the admin would have been virtually unusable without a large
amount of reimplementation to adapt it to our internal code.

Pyramid was a big win for us in that it used our preferred backend choices by
default. More importantly, though, was that it's comparatively very easy to
change those defaults without losing the rest of Pyramid's features. After a
couple of hours of experimenting with integrating our legacy codebase, I had
new pages up and running.

I have nothing bad to say about Django and I've used it successfully in other
projects. It's a neat framework with a lot of talented people behind it. But
Pyramid has its own charms, especially for those who absolutely need to do
things their own way.

