TG/web2py comparison

171 views
Skip to first unread message

Jens Østergaard Petersen

unread,
Apr 23, 2009, 3:36:16 AM4/23/09
to TurboGears
Hi

I am new to this group. I am not into TG yet, but we have to take a
decision whether to use TG or web2py for a project. The other part is
opting for web2py, referring to a comparison made by web2py at <http://
mdp.cti.depaul.edu/AlterEgo/default/show/102>. I have only been able
to find a few mailinglist contributions comparing the two, nothing
solid. How do these two frameworks compare? Wouldn't it be a good idea
for TG to have a comparison on their web site?

Cheers,

Jens

Antoine Pitrou

unread,
Apr 23, 2009, 5:42:58 AM4/23/09
to TurboGears
The comparison above seems to refer to TG1, which is quite outdated.
The only thing I know about web2py is that it doesn't use SQLAlchemy
but its own ORM, which for me is quite a no-go.

Regards

Antoine.

Timmie

unread,
Apr 23, 2009, 3:42:49 PM4/23/09
to TurboGears
> The only thing I know about web2py is that it doesn't use SQLAlchemy
> but its own ORM, which for me is quite a no-go.
Could tell us a bit more, please?

I do not know how SQL works. Only worked with pytables so far.
But the 2 weeks I am playing with web2py, I have felt that it's ORM is
quite easy.

I am no a professional webapp writer since I mostly use python for CLI
scripting. So I am really interested in the key issues a webapp pro
looks at for his choice.

What I really liked that it's self-contained.
Not so many eggs to fetch before you start. and zero-config.
But I never really tried to used turbogears. Djange at least seemed to
complex for me.

Thanks in advance,
Timmie

Jens Østergaard Petersen

unread,
Apr 24, 2009, 5:39:34 AM4/24/09
to turbo...@googlegroups.com
Interesting posting! How many people _not_ using TG subscribe to the
TG list? I had an off-list reply from the web2py developer -
presumably he has run TG, but why does he not reply on-list?

Thanks to Antoine for his reply, but if no more TG users rise to the
occasion to compare these two very similar frameworks, I might as well
go with web2py.

Cheers,

Jens

Antoine Pitrou

unread,
Apr 24, 2009, 6:05:39 AM4/24/09
to TurboGears
On Apr 23, 9:42 pm, Timmie <timmichel...@gmx-topmail.de> wrote:
>
> I do not know how SQL works.

If this isn't a typo and you /really/ don't know how SQL works, the
first you should do is learn about it. Using an ORM without knowing
SQL and the characteristics of a relational database is a big mistake.

> But the 2 weeks I am playing with web2py, I have felt that it's ORM is
> quite easy.

It is not about simplicity. The database is where all your data is
stored, and retrieved from. You should care about it a bit more than
under the sole angle of being "easy". And SQLAlchemy looks like the
very best choice nowadays for people wanting to have full control of
their relational database.

> Djange at least seemed to
> complex for me.

Well I fear that if Django seems too complex for you, TurboGears will
look even worse in your eyes...

Antoine Pitrou

unread,
Apr 24, 2009, 6:08:33 AM4/24/09
to TurboGears
On Apr 24, 11:39 am, Jens Østergaard Petersen <oest...@gmail.com>
wrote:
> Interesting posting! How many people _not_ using TG subscribe to the  
> TG list? I had an off-list reply from the web2py developer -  
> presumably he has run TG, but why does he not reply on-list?

Maybe because Google Groups is a real pain in the ass.
(subliminal message to open source projects out there : please use
decent project management tools. Sometimes it's a real pain to get
interested in, and contribute to your projects)
Message has been deleted

Francisco Gama

unread,
Apr 24, 2009, 7:51:35 AM4/24/09
to TurboGears
I do. I know Turbogears well, I was user of it and I really like it.

Turbogears name is quite related with its inside. "Gears plugged into
each other". It's philosophy goes completely against reinventing the
wheel. Kevin Dangoor, the founder picked on many open good open source
projects for small tasks and connected them to each other and best of
all he had the vision to make the way you plug these internal
components very seamless.
I would say Turbogears stands on a great philosophy and it's main
strength comes with its high flexibility...
you don't like SQL Object? Fine, plug in SQL Alchemy!
you don't like Kid? Fine, plug in mako or genshi or whatever
you don't like catwalk? Fine, plug in dbsprockets or dbmechanic
you don't like cherrypy? Fine, plug in other framework
you don't like Mochikit? Fine, use Mootools or dojo
like SQL Alchemy but don't like SQL Alchemy? use Elixir!

even the lib's that run underneath can be changed... and this brings
us to the downside of it.
All this jungle of independent components always getting updated make
you easily fall in terms of stability and backwards compatibility. And
the (not) funny thing, is that with such a variety some times you may
have trouble to find support because most people use other
"combination" of "gears" where your question is not applied. Specially
if you try to use the latest stable version with default packages
instead of the latest (never ending) "beta".

Turbogears is that framework developed by very technical guys that
tries to keep on the edge technologically speaking and someday
eventually they will care about real stability.
If you go for Turbogears I really recommend you to do it inside a
virtualenv ( http://pypi.python.org/pypi/virtualenv ).

web2py is more solid. It really offers backward compatibility and
while it's not so so flexible, it's a little more concise and straight
forward to program with it. You don't need configuration files, you
don't injure yourself with them, you don't even need an IDE! The idea
of bringing a web interface with CRUD, good application management,
ticketing support for error support, integrated IDE with Testing
support is really useful and well achieved.
web2py is that package where all components know about each other
because it's smaller and ruled by the same guy coming a ready-to-go
bundle. It's very low learning curve requirement and it's stability
are its main strengths in my opinion.

Once, I made a comparison with all the frameworks I've worked with and
I would say my conclusion is that quite irrelevant what you use. There
are betters and worsts, but both Turbogears and web2py were on top so
what really counts is the right tool for the right job and your
personal taste (and knowing how to work with it).

you, make your choice!

Best regards,
Francisco Gama T.R.

On Apr 24, 10:39 am, Jens Østergaard Petersen <oest...@gmail.com>
wrote:

Jurgis Pralgauskis

unread,
Apr 24, 2009, 8:57:34 AM4/24/09
to TurboGears
Hello,

I tried TG1 (and used for a while), tried few first steps with Django
I like web2py most because of it's simplicity and clearness...
(same as py compared to other langs ;)

> The only thing I know about web2py is that it doesn't use SQLAlchemy
> but its own ORM, which for me is quite a no-go.

here it says
web2py DAL understands Django and SQLAlchemy models
http://www.web2py.com/AlterEgo/default/show/189


I hear people saying Pylons has very good approach (WSGI)
in terms of reusability...
in http://en.wikipedia.org/wiki/Web2py I see
Web2py is built following the WSGI protocol

so Pylons/TG2 could be kind of intermixed with web2py, if needed...

mdipierro

unread,
Apr 24, 2009, 3:44:33 PM4/24/09
to TurboGears
LOL

I did not reply because I do not want to start a war. So I am not
going to make any serious comparison on this list. Come to our list
for that.
I have used TG a lot in the past. I have made a software for online
portfolio analysis with it (TG1).
I have also used Django a lot and made the portal of UN missions with
it (http://www2.un.int).
I am on this list because somebody pointed me to this thread, I am not
normally spying on you. ;-)

To be honest I have not used TG2 much but I am familiar with its
components, in particular Genshi and SQLAlchemy.
I really like both of them but in web2py we took a different approach:

Genshi is designed specifically for generating HTML/XML documents. The
web2py template system is pure Python (similar to Mako but without
indentation requirements) because we are very much interested in
generating JS programmatically as well as XML/HTML. We have a lot
going on in that direction recently. You can use Genshi with web2py if
you install the module.

SQLAlchemy focuses exclusively on relational databases and does not
set restrictions on which tables can be accessed. This makes it great
for legacy databases. web2py's DAL instead was designed to force the
developer to follow good practice (as we defined] it): every record
must have a unique auto increment id field and this record must be
used for references. This means web2py cannot access all legacy
databases as SQLAlchemy does. Nevertheless this constraint allowed us
to create a sophisticated CRUD + web services structure that works on
both relational databases and non-relational databases (such as the
Google App Engine).

You can use SQLAlchemy with web2py if you install the module but it
will not have the ability to generate CRUD forms automatically for
you. You need the web2py DAL for that.

You can also use some SQLAlchemy and Django models with web2py WITHOUT
installing SQLAlchemy and Django because web2py understands 90% of
their syntax (we have compatibility modules). In this case you do not
loose any web2py functionality. This is designed to help you port
existing applications but it is not a recommended way of coding.

Conversely you can use the web2py template system and the web2py DAL
with TG and Pylons if you like (but I do know know anybody doing it
and I cannot think of any good reason for doing so).

If you need SQLAlchemy you should use TG2 or Pylons.

This brings up a question I have and I have not had a decent answer
to. Other than for accessing legacy databases why would one need
SQLAlchemy over the web2py DAL? What functionality is missing in th
web2py DAL that is in SQLAlchemy? Please understand I am not trying to
be polemic, far from it, I am trying to learn from you so that we can
improve.

For new users anyway the difference in syntax for the DAL or the
template syntax is probably not the most important feature difference
between the two frameworks. I believe the biggest different is in the
time to setup them and become productive.

I sent Jens a private email saying that he should should try them both
(5 minutes each, no more) and let us know what he thinks.

I hope everybody realizes that we are not in competition and our
"success" or "market share" are positively correlated. We are both
based on Python, our users share very similar knowledge and
experiences.

Massimo

Sam

unread,
Apr 25, 2009, 3:25:14 AM4/25/09
to TurboGears
On Apr 24, 3:05 am, Antoine Pitrou <antoine.pit...@gmail.com> wrote:
> On Apr 23, 9:42 pm, Timmie <timmichel...@gmx-topmail.de> wrote:
>
>
>
> > I do not know how SQL works.
>
> If this isn't a typo and you /really/ don't know how SQL works, the
> first you should do is learn about it. Using an ORM without knowing
> SQL and the characteristics of a relational database is a big mistake.

Antoine gives good advice...

But...there are only so many things you can learn at a time. You can
probably get by without an understanding of SQL for a little bit, as
long as your website doesn't do too much or have too many hits. :)

But eventually you may find you have to rework quite a bit of your
code/models to get better performance.

So while you are just starting out:

- if you can make the ORM do what you want,
- and it does it fast enough
- and you aren't going to see a large increase in traffic any time
soon

Don't sweat learning SQL....at some point you'll want to/need to
understand it more. But you can't learn everything at once.

Adrian von Bidder

unread,
Apr 25, 2009, 5:01:12 AM4/25/09
to turbo...@googlegroups.com
On Friday 24 April 2009 21.44:33 mdipierro wrote:
> SQLAlchemy focuses exclusively on relational databases and does not
> set restrictions on which tables can be accessed. This makes it great
> for legacy databases. web2py's DAL instead was designed to force the
> developer to follow good practice (as we defined] it): every record
> must have a unique auto increment id field and this record must be
> used for references.

you asked for it...

> This brings up a question I have and I have not had a decent answer
> to. Other than for accessing legacy databases why would one need
> SQLAlchemy over the web2py DAL?

Without having looked into DAL at all: alone from the description above, it
makes me instantly dislike it. (If you're starting to foam at the mouth
already: jump to the last paragraph and come back here.) I like to control
the database. I know SQL, and when I design my database schema, I do it as
"desigining a db schema". The model in a web application *may* be a good
way to specify it, but ultimately, I want to be in control about what tables
get created, what the columns are, how the primary key is built etc.

Yes, I understand that being able to make assumptions about stuff like
"autoincrement primary key on every table" allows for some beautiful and
quite stunning optimisations/automatisms, and being my own master in terms
of DB layout makes me pay for it by not having these simplifications
available. OTOH with the 'make some assumptions' kinds of frameworks I'm
always afraid that these assumptions will bite me at some point where what I
want suddenyl doesn't match with what the framework designers think how
stuff should be done.

Please take this as what it is: pure opinion. Like: When somebody doesn't
like Pizza it doesn't mean Pizza is bad, but just that he doesn't like it.

cheers
-- vbi

signature.asc

Dan F

unread,
Apr 25, 2009, 11:48:27 AM4/25/09
to turbo...@googlegroups.com
mdipierro wrote:
> This brings up a question I have and I have not had a decent answer
> to. Other than for accessing legacy databases why would one need
> SQLAlchemy over the web2py DAL? What functionality is missing in th
> web2py DAL that is in SQLAlchemy? Please understand I am not trying to
> be polemic, far from it, I am trying to learn from you so that we can
> improve.
>

It's not just "legacy" databases. Calling them legacy makes it sound
like only old databases are designed against the wishes of ORMs like
web2py. I know quite a few developers who simply won't tolerate poor
table structure, and too often these ORM's dictate a pattern that is
less than ideal (as I have defined it ;-) ). Disallowing/discouraging
compound primary keys, for example, sacrifices traditional design to
make it easier on ORM developers, or in the case of web2py, to allow it
to be abstracted to even allow non-relational databases.

Anyway, I consider traditional design to be important. I prefer my
model to be proscriptive as well as descriptive. The more I can get my
data model working to define structure, the less pain later. There's a
large class of developers who don't really care. That's fine, and maybe
they won't ever need to use a fuller extent of the database's power
anyway, but I have yet to see this as the "future" of web apps that
throws most databases I've seen into the "legacy" category. Plus it
assumes that I have full control over the database, and that the
database is used for no other purpose or at least mainly used by that DAL.

Does the web2py DAL allow batch updates etc. to occur without recourse
to actual SQL statements? i.e., updating all columns in the database
without making a call per record? If not, functionality like this gives
SQLAlchemy perhaps another benefit.

I'm interested to hear what others think of this. Is the database
structure less important than I'm making it out to be?

Antoine Pitrou

unread,
Apr 25, 2009, 1:21:12 PM4/25/09
to TurboGears
On Apr 24, 9:44 pm, mdipierro <massimodipierr...@gmail.com> wrote:
>
> Other than for accessing legacy databases why would one need
> SQLAlchemy over the web2py DAL? What functionality is missing in th
> web2py DAL that is in SQLAlchemy?

Well, documentation at least ;-)
And since online documentation for web2py's ORM seems scarce, it's
difficult for me to find out which features of SQLAlchemy it does or
doesn't support.
If you read the SQLAlchemy documentation, you'll see that the feature
set is quite massive and covers a *lot* of use cases. It is, at least,
good to know that one likely won't be limited by the power of the
database access layer.

Regards

Antoine.

Jorge Godoy

unread,
Apr 25, 2009, 6:18:10 PM4/25/09
to turbo...@googlegroups.com
I second your words.

Using compound keys allows for much better design on several use cases where using autoincrement keys would require extra tables or extra joins (or some database denormalization to couple with the limitation of having autoincrement keys only).

Also, CRUD is important, but it is not all that hard to implement your own structure and code to be able to optimize the database.  If you're dealing with massive amount of data, then database optimization is a concern.  For toy projects it doesn't matter as a badly written database will probably be faster than network latency anyway...

I design my database to couple with web and GUI tools.  SQL Alchemy can be used independent of the interface, so it doesn't restrict me to design my application as targeting some specific environment.

I also like to use all what my database offers: triggers, stored procedures / function, namespaces, views, transactions, etc.

As my database is a database -- and not used only for data storage --, I have application logic in there to guarantee the consistency of the information, no matter if it is accessed from a GUI application written in Java, C, C++, Python or a web application written in any language (or even PHP ;-)).  I can also use the database CLI to manipulate data and since there's code in there to prevent things from going wrong, it is safe to do maintenance through the CLI as well as take some reports or do some kinds of changes and I'm sure that data integrity is OK.

What SQL Alchemy offers, then, is freedom to design and optimize the database in a way that the developer things is correct, not the way SQL Alchemy think it is or the way TG / Pylons / whatever think it is.  Empowering the developer is a good thing.

From TG 0.x, we've learned a lot of things that should have been changed with regards to components.  The end result from those changes gave the developer more freedom (APIs allowed for different template engines, different ORMs, use of decorators, etc.).

From TG 1.x, we've learned that freedom is good and then there's the move to TG2, where this freedom is increased through the usage of WSGI, the decoupling of several parts of TG from its core and all that leading to grant the developer a better way to design HIS / HER application.  We're removing limitations and providing a clear API and tool stack to allow the developer do what HE / SHE wants.

I value TG for the freedom I have.  Should it be easier if we had less choices?  Indeed, but then, would we be able to think better apps?  Or would we be forced to write code "TG-way"?

When the only tool you have is a hammer, all your problems start looking like nails.

--
Jorge Godoy     <jgo...@gmail.com>

mdipierro

unread,
Apr 25, 2009, 7:52:03 PM4/25/09
to TurboGears
On Apr 25, 10:48 am, Dan F <danielfal...@gmail.com> wrote:
[...]
> Does the web2py DAL allow batch updates etc. to occur without recourse
> to actual SQL statements?  i.e., updating all columns in the database
> without making a call per record?  If not, functionality like this gives
> SQLAlchemy perhaps another benefit.

If I understand the statement: yes we can. for example say I have a
table "mytable" with a field1 and a field2 and I want to update every
record that has field1==0 and set its value to the value of field1+2
and the value of field3 to 0.

db(db.mytable.field1==0).update(field1=db.mytable.field2+2, field3=0)

You can have complex conditions and update more columns in the same
statement.

Anyway this thread nailed a major difference between SQLAlchemy and
web2py. SQLAlchemy gives you more freedom than web2py (because web2py
forces all records to have a autoincrement ID). If this is important
for you use SQLAlchemy. This does not mean that in web2py you cannot
handle tables that have other constraints (as long as they also have
the auto increment ID). web2py can also handle very complex
constraints that cannot even be declared in SQL at the framework level
using validators that talk to the database.

Personally I believe that designing a database schema that does not
have a autoincrement ID is a mistake and this is why web2py enforces
it. This buys us a lot of other goodies that other ORMs do not have.
For example automatic forms and the ability to assign uuids to records
for import/export/merge of databases (web2py can export an entire
database in Oracle and reimport it on MSSQL or Google App Engine
without breaking references even if the autoincrement IDs of the
source and destination may be different).

Anyway, I am not comfortable with talking about web2py on this list.
As I said I very much like TG and its developers. But if you ask me
questions I feel compelled to answer.

Massimo

Dan F

unread,
Apr 25, 2009, 11:38:55 PM4/25/09
to turbo...@googlegroups.com
mdipierro wrote:
> On Apr 25, 10:48 am, Dan F <danielfal...@gmail.com> wrote:
> [...]
>
>> Does the web2py DAL allow batch updates etc. to occur without recourse
>> to actual SQL statements? i.e., updating all columns in the database
>> without making a call per record? If not, functionality like this gives
>> SQLAlchemy perhaps another benefit.
>>
>
> If I understand the statement: yes we can. for example say I have a
> table "mytable" with a field1 and a field2 and I want to update every
> record that has field1==0 and set its value to the value of field1+2
> and the value of field3 to 0.
>
> db(db.mytable.field1==0).update(field1=db.mytable.field2+2, field3=0)
>
> You can have complex conditions and update more columns in the same
> statement.
>
Very cool. This syntax looks nice.
> <snip>

>
> Personally I believe that designing a database schema that does not
> have a autoincrement ID is a mistake and this is why web2py enforces
> it.
I do not call it a mistake by any means, and I'm not even talking about
the debate between natural vs. surrogate keys here. Autoincrementing
IDs are fine and great. Usually preferable. There are however times
where it makes very good sense from a db designer's point of view to
combine more than one of these autoincrement ids. The common example is
a linking table in a many-to-many. I consider the most sensible PK for
a linking table to be the combination of the PK's of the tables that are
linked. Otherwise you're left to define yet another column along with
the index that needs to be put on what would otherwise be indexed as PK.

Another less common but probably more illustrative scenario is the
"Diamond" relationship, where there's a parent, multiple child tables,
and then a table which references specific combinations of the children:

Parent
- parent_id PK

LeftChild
- leftchild_id PK
- parent_id PK,FK

RightChild
- rightchild_id PK
- parent_id PK,FK

ChildCombo
- childcombo_id PK
- rightchild_id FK
- leftchild_id FK
- parent_id FK

In this scenario, the ChildCombo must reference a left and right child
which share the same parent. My compound FK can do this since the two
child tables have taken on the parent's PK as part of their own.

Now I'll grant that possibly a majority developers aren't going to care
enough to design it out this way. They're happy to allow the "same
parent" constraint to fall by the wayside in order to simplify the
design. But I think it's best to let the database care for this if you
can, and I certainly wouldn't call doing so a mistake. But that for me
is the bigger difference between SQL Alchemy and the simpler ORMs...not
so much the freedom, but the philosophy of SQL Alchemy that wishes to
let the database play its strengths, even if it means less of an
abstraction. The thing about abstractions of course, is that they end
up playing to the "lowest common denominator" of all implementations.

> This buys us a lot of other goodies that other ORMs do not have.
> For example automatic forms and the ability to assign uuids to records
> for import/export/merge of databases (web2py can export an entire
> database in Oracle and reimport it on MSSQL or Google App Engine
> without breaking references even if the autoincrement IDs of the
> source and destination may be different).
>

Here's the great part about the web2py abstraction in my opinion. It
would be very cool to take an app that runs off a database and just drop
it into AppEngine. No way that's going to work with SQL Alchemy. The
philosophy of SA is such that it just wouldn't be done.


> Anyway, I am not comfortable with talking about web2py on this list.
> As I said I very much like TG and its developers. But if you ask me
> questions I feel compelled to answer.
>

I actually appreciate your talking about web2py on this list. I
wouldn't have gotten to know so much about it otherwise, and I am the
better for it. Plus it helps to show what TurboGears is about when this
comparison is made.

mdipierro

unread,
Apr 26, 2009, 1:24:29 PM4/26/09
to TurboGears
Thanks Dan, interesting example:

> Parent
> - parent_id  PK
>
> LeftChild
> - leftchild_id  PK
> - parent_id  PK,FK
>
> RightChild
> - rightchild_id  PK
> - parent_id  PK,FK
>
> ChildCombo
> - childcombo_id  PK
> - rightchild_id  FK
> - leftchild_id  FK
> - parent_id  FK

I agree that you do not need a unique ID but you can do the same if
you have one. In web2py this is doe under the hood:

db.define_table('parent',
db.Field('name'))
db.define_table('left_child',
db.Field('name'),
db.Field('parent',db.parent))
db.define_table('right_child',
db.Field('name'),
db.Field('parent',db.parent))
db.define_table('child_combo',db.Field('name'),
db.Field('left_child',db.left_child),
db.Field('right_child',db.right_child),
db.Field('parent',db.parent))

Note that I do not define the ID but it is there and handled for you.
You can make "name" unique using validators.

I agree that having the ID does not help you here but if in the future
you decide that these children can have an additional attributes and
you can have multiple left_child with same parent and same name but
different attributes in your case you have nightmare. With the unique
ID you do not need to change your database schema but only add those
attributes to one table and your data will migrate.

Massimo
Message has been deleted

greenpoise

unread,
Apr 26, 2009, 7:13:55 PM4/26/09
to TurboGears
My posts never made it, none of them. I dont think I want to write all
of it again but in a nutshell
my observations after three days of using/reading about web2py and
years/months trying to be
up to pace with Turbogears are these:

*SQLAlchemy is just a facilitator. RDBM will always be RDBM. Using
SQLAlchemy or not. Good design
DB design will work on anything using any well handed tool.

*Documentation, Documentation and Documentation. I love how Web2Py put
things together. The examples
could lead me to a complete project. I have a TurboGears book and I
keep struggling because examples
are just not complete or well commented (not trying to be bad to TG,
on the contrary, is a constructive critic).
An it totally drifted me away from trying to catch up with TG2. I need
quick ways of doing things that will
get me going on others.

I love TurboGears because it exposed me to a great framework for me to
transition from client-sever applications
to web applications. HOWEVER, I am totally sold by the ideas/structure
of web2py and after dealing with TG,
everything was clearer and simpler in web2py.
But for me what it all boiled down to was Documentation. I think it is
all well presented in web2py and not TG.

This is just my opinion. Great job in both cases. I will be watching
both projects closely anyways.


Dan.

Antoine Pitrou

unread,
Apr 27, 2009, 7:25:58 AM4/27/09
to TurboGears
On Apr 25, 9:12 pm, greenpoise <danel.sega...@gmail.com> wrote:
> > Well, documentation at least ;-)
>
> I must disagree.

I was talking about SQLAlchemy, not TurboGears.

Web2py's ORM (online) documentation is ridiculous compared to
SQLAlchemy's.

Michel Albert

unread,
Apr 27, 2009, 9:38:40 AM4/27/09
to TurboGears
For me, many points of this discussion apply. And I'll try to put it
in a way to fulfill Jens' original question. That is, arguments for
and against TG and web2py. First off, I have not yet looked into
web2py at all. Honestly, today marks the day that I first even heard
about it ;) But two importand points emerge from this thread without
even looking at (or knowing) either. These two points are:

- Documentation
- Database interface

I am sure that there are other prominent differences, but I do not
like to guess. So I'll try to digest the information I read in this
thread and inject some of my own thoughts. As said, I am not familiar
with web2py, so I'll keep it short on that end.

Documentation
===========

Documentation has two main audiences. Newcomers and - let's call them
- veterans. For newcomers it's extremely important to get to grips
with a new system quickly and without exposing too much of the inner-
workings of the framework. That is something that can be picked up on-
the-go. Frankly, TG's documentation is mediocre. Out of boredom/
curiosity/..., I decided to work through the quickstart tutorial
yesterday and found it not working. I consider myself very familiar
with Python and (maybe to a lesser extent) TG so I was quickly able to
solve the problems. Newcomers are surely put off by something like
that.

I have not yet looked much into the docs about TG2, but I remember
those of TG1 quite well. One thing that is very important in *any* web-
applications are forms. Diving into forms in TG can be quite daunting
especially if you go into form validation. The trouble comes from TG's
flexibility as you can work pretty much the way you like. In my
opinion TG is missing some "Best practices" in this area (and others).
The Wiki Tutorial (if it's working), gives you all that is necessary
to get you started. But after that it feels like there is a large
black hole somewhere sucking in all the important information.

Some people recommended me to just "look it up in the source code".
And at first I thought: "You can't be serious!?" Coming from a PHP
background where the source code of many FOSS projects is a big jungle
infested with spaghetti monsters, I really did not intend to even
*start* looking into the code. Eventually I gave in and did it anyway
and boy was I surprised! The code looks clean and is very well
documented. Thumbs up for that ;) This is a very cool thing for the TG
"veterans". Not so much for newcomers.

From the earlier posts in this thread, I gather that this is an area
where web2py definitely has a big advantage over TG. The way it
sounds, web2py is very straight-forward to use as it's documentation
does not get in the way. This is very cool for newcomers or people
that try to evaluate the framework and compare it with others. After
you have the overview of how the components are strung together, it
all boils down to reference. This is something I cannot elaborate for
web2py. Only people that have been working with it for a while can
give valid feedback. That rules me out ;) As for TG, it's not all too
bad even. As TG builds on other well known frameworks, you can rely on
the docs from these. For me the two most important references here are
that of the database abstraction ( SQLAlchemy in my case) and the
webserver (cherrypy). The docs of SA are amazingly complete. And well
explained. So, many thumbs up there! On the other hand, the docs of
CherryPy are so-so. You can figure out most of the details, but more
advanced features show more gaps (see the end of the following
document for example: http://www.cherrypy.org/chrome/common/2.2/docs/book/chunk/ch03s03.html#id3507420).
But that's not TG's fault/problem. When it comes to looking at TG, as
I said earlier the source code is clean and well documented. So with
only a little bit of digging you can find all you need.

But then again, TG adds a dash of abstraction on top of the existing
frameworks. I'll note the "expose" decorator and TG2's "DBSession"
object as examples. Unfortunately, the differences between the
original framework's concepts are not well documented. And even after
working for a while with TG now, they are a mistery to me.

I have the gut feeling though that TG2 will do much better. Also in
the documentation.



Database interface
==============

As has been mentioned already, the importance of this element depends
strongly on your needs. A long while ago, I started to redesign an old
web-page and considered to give Ruby on Rails a try. That was short
lived. At the time, the database boasted a whopping 86 tables. And
it's growing. In that database I've got a lot of natural pkeys (some
of them composite), and also quite a lot of surrogate pkeys. Putting
that in a framework as restrictive as the RoR one was a no-go.
Enforcing that each table has a "id" column posing as primary key was
the first show-stopper. But we're not here to discuss RoR. But from
what I see, web2py makes the same assumption. Don't get me wrong. This
is not necessarily a bad (or evil) thing, it solely depends on your
needs. As for my pet-database, I had no trouble at all to get it
working in SQLAlchemy. A *very* important thing here, that most ORMs
silently ignore, are relations with attached attributes. Consider the
classical example of invoices ( [user] [orders] [item] ). Now, a user
can surely order an item n times. One way of modeling this is as
follows (i'll put primary keys in brackets):

User( [user_id], fname, lname, ... )
Item( [item_id], label )
ItemOrder( [user_id, item_id], amount )

This shows a many-to-many relationship (ItemOrder) with an attached
attribute (amount). Modeling this in SQLAlchemy was very easy. And
it's a very common situation. How well web2py handles this, I cannot
say.

On the bottom line though, as already said, it depends on your needs.
If you only have straight-forward tables and relationships, that is to
say, simple one-to-many and man-to-many relationships without
attributes, and not table inheritance, then it's safe to say that it
does not matter what ORM you use. All of them can handle this very
well. Bear in mind though, that over time the database might grow. We
all know this, the client inevitably will change his requirements or
come up with new ideas and you need to adapt the software. This can
very easily reach down to the database level. If right now, your model
looks simple and easy, in two years time this might not be the case
anymore. If the ORM you chose cannot handle upcoming model changes
you're in for a treat. If however, you can say that the requirements
of your application are rock-solid and won't change in the future than
you can go for more restrictive (and thus simpler) solutions. It all
depends on the size of your application.

Something else to bear in mind: As already mentioned in an earlier
post, the more of your model you get into the database, the more
robust your application will become. As a side-effect the application-
logic code will be much simpler. Triggers and properly configured
foreign key constraints can be a boon to every application. But also
table structure affects the resulting application code a lot. With
natural keys (even if composite) you can even avoid some SQL joins
while still retaining all required data.


Finishing thoughts/Summary
=====================

Whether to use web2py or Turbogears depends largely on application
size and scope. The way it looks to me, web2py is good for small inert
projects, and TG offers all the flexibility in the world needed for
large-scale apps. Additionally I beleive it still worthwile to start
even small projects using TG. Primarily because you will be prepared
for unexpeced changes in the application.

While writing this, I skimmed through the web2py "cookbook" tutorial,
and a few things popped into my mind. First, why make the tutorial
only available in PDF? Plain HTML would read so much easier, but
that's only my opinion. What's worse, the tutorial defies good code
style for python. Mainly because it collapses some lines into one and
leaves out too much valuable whitespace which makes it harder to read.
Also, it uses a funtion "T" for i18n translation. Why a *capital*
"T"? Why not use the widespread "gettext"-standard and name the
function "_" ? These are only minor glitches I saw, also I only looked
briefly under the hood so I ask myself: "Are there more of these
surprises?" I am a big fan of standards (whether exmplicit or
implicid). They are there for a reason. Use them!

I think greenpoise's posts make it clear, that TG2 easily scares off
newcomers. If you don't have the tenacity to really "dig in" you'll be
disappointed by TG. But if you *do* dig in (which for me is always the
fun part) you get to see the hidden beauty and coolness of TG :P

I hope I made sense and was not too biased. I can only repeat that I
do not know enough about web2py to make a fair judgement. Please keep
that in mind! If anything I wrote is incomplete or even totally wrong,
I'd be glad to hear Massimo's comments. I beleive his comments it
would benefit Jens a great deal as well.

As I'm too lazy too proof-read this chunk of text, I'll just blindly
click on the "send" button right now. So my apologies for nonsense
sentences ;)

mdipierro

unread,
Apr 27, 2009, 10:04:56 AM4/27/09
to TurboGears

> User( [user_id], fname, lname, ... )
> Item( [item_id], label )
> ItemOrder( [user_id, item_id], amount )

> This shows a many-to-many relationship (ItemOrder) with an attached
> attribute (amount). Modeling this in SQLAlchemy was very easy. And
> it's a very common situation. How well web2py handles this, I cannot
> say.

db.define_table('user',SQLField('fname'),SQLField('lname))
db.define_table('item',SQLField('label'))
db.define_table('order',SQLField('user',db.user),SQLField
('item',db.item),SQLField('amount','double'))

purchases=(db.user.id==db.order.user)&(db.item.id==db.order.item)
rows=db(purchases).select(db.user.ALL,db.item.ALL,db.order.amount)

for row in rows:
print row.user.fname, row.user.lname, row.item.label,
row.order.amount

Of course we can do aggregates too

total=db.order.amount.sum()
rows=db(purchases).select(db.user.ALL,total,orderby=db.user.lname|
db.user.fname,groupby=db.user.id)
for row in rows:
print row.user.fname, row.user.lname, 'spent', row._extra
[total]

I'd argue that we do not need as much documentation for the DAL as
SQLAlchemy because it more intuitive. But this is a personal opinion.

Massimo

Michel Albert

unread,
Apr 27, 2009, 12:12:00 PM4/27/09
to TurboGears
On Apr 27, 4:04 pm, mdipierro <massimodipierr...@gmail.com> wrote:
> > User( [user_id], fname, lname, ... )
> > Item( [item_id], label )
> > ItemOrder( [user_id, item_id], amount )
> > This shows a many-to-many relationship (ItemOrder) with an attached
> > attribute (amount). Modeling this in SQLAlchemy was very easy. And
> > it's a very common situation. How well web2py handles this, I cannot
> > say.
>
>     db.define_table('user',SQLField('fname'),SQLField('lname))
>     db.define_table('item',SQLField('label'))
>     db.define_table('order',SQLField('user',db.user),SQLField
> ('item',db.item),SQLField('amount','double'))

This does indeed look very simple and straightforward :) I can grok
this without reading the docs even :)

>     purchases=(db.user.id==db.order.user)&(db.item.id==db.order.item)
>     rows=db(purchases).select(db.user.ALL,db.item.ALL,db.order.amount)

However, this I cannot parse clearly in my head. But that's certainly
because I do not actively work with DAL.

> I'd argue that we do not need as much documentation for the DAL as
> SQLAlchemy because it more intuitive. But this is a personal opinion.

I would say "yes". Everyone has different ways of looking at problems.
What might seem intuitive to you might not be so for someone else.
This is a very common problem when designing user interfaces. And in a
certain way, an ORM is a textual user interface to the underlying
database. Last week I had a 30min discussion (no, seriously) about the
text and icon of a button which changes between two totally different
states (which means it was *not* an on/off button). Space was limited,
so writing too much text was out of the question, so we discussed
about which image to use. Eventually I decided, if this is already an
issue between us two developers, we needed to redesign that button
because it would surely confuse end-users. But when thinking about the
use-case, everything was totally obvious to me. Not so for my co-
worker ;)

I believe this analogy hold very true as well for any library. You
might think it intuitive, others might think not. And to those people,
an extensive doc would help to clarify things. But, from what I've
seen so far, DAL looks mostly intuitive to me as well.

Jens Østergaard Petersen

unread,
Apr 27, 2009, 12:38:57 PM4/27/09
to turbo...@googlegroups.com, Anand Mishra
Being the one who started this thread, I wish to thank all posters for
their contributions. They have been full of information, good
judgement and civility. A lot of ground has been covered and the
differences between the two frameworks are now much clearer to me -
and, hopefully, to everyone.

I did not state what we intended to use either of these two frameworks
for, which was a mistake on my part. We are deciding which framework
to use as the core element in the IT architecture of a research
institute at a European university. I hit on TG and a colleague of
mine hit on web2py, and we needed arguments pro et con. This you have
now have now supplied, in abundant - and perhaps sufficient - measure.

Thanks to all!

Jens

PS: Keep the thread spinning!

mdipierro

unread,
Apr 27, 2009, 12:41:20 PM4/27/09
to TurboGears
I agree with you.

> > purchases=(db.user.id==db.order.user)&(db.item.id==db.order.item)
> > rows=db(purchases).select(db.user.ALL,db.item.ALL,db.order.amount)
>
> However, this I cannot parse clearly in my head. But that's certainly
> because I do not actively work with DAL.

Anther way the DAL differs from SQLAlchemy is that the former has very
few keywords. We try to do as much as possible with operators.

With some exceptions all web2py queries have the following syntax

db([where clause]) defines a set
db([where clause]).select([what you what to select], [how you want to
select them])

The code above (db(purchases)....) generates

SELECT user.id, user.lname, user.fname, item.label, order.amout from
user, item, order WHERE user.id=order.user AND item.id=oder.item;

Here are some more examples:
http://www.web2py.com/examples/default/dal

Massimo
Reply all
Reply to author
Forward
0 new messages