Skip to main content

FormAlchemy 1.0

A little background: a few months ago, I went looking for a web framework that was good at automating CRUD (create/retrieve/update/delete) against an existing database schema. I tried django but its database introspection abilities are beyond feeble, and django-sqlalchemy was not mature enough. I tried dbmechanic but its dozen-plus dependencies, most of which were alpha-quality, gave me pause; so did its basic architecture on top of toscawidgets, which I think is The Wrong Way to build web apps. (I understand that the former problem has since been reduced; the latter has not.)

So, I went back to option #3, FormAlchemy. I knew SQLAlchemy could reflect very hairy schemas indeed, and what it could not reflect, it could certainly represent with a little manual help. And FormAlchemy was a decent start to automating CRUD with SA models. I added the ability to represent relations, automatic syncing of form input back to SA objects, Grid support, and a test suite. Then Gael came along and added internationalization, support for even more SA features, and Sphinx docs. Along the way we've killed enough bugs and added enough test cases (yes, the two are related) that we think we have a pretty solid release. Especially since I just released 1.0.1 fixing the most obvious problems. :)

I think all three FA committers use it mostly with Pylons; that said, FormAlchemy has no dependencies besides SQLAlchemy itself. You could easily use it with werkzeug or web.py or whatever.

Here, finally, is a quick FormAlchemy tutorial:

To get started, you only need to know about two classes, FieldSet and Grid, and a handful of methods:

  • render: returns a string containing the html
  • validate: true if the form passes its validations; otherwise, false
  • sync: syncs the model instance that was bound to the input data

This introduction illustrates these three methods. For full details on customizing FieldSet behavior, see the documentation.

We'll start with two simple SQLAlchemy models with a one-to-many relationship (each User can have many Orders), and fetch an Order object to edit:

 from formalchemy.tests import Session, User, Order
session = Session()
order1 = session.query(Order).first()

Now, let's render a form to edit the order we've loaded.

 from formalchemy import FieldSet, Grid
fs = FieldSet(order1)
print fs.render()

This results in the following form elements:

Note how the options for the User input were automatically loaded from the database. str() is used on the User objects to get the option descriptions.

To edit a new object, bind your FieldSet to the class rather than a specific instance:

  fs = FieldSet(Order)

To edit multiple objects, bind them to a Grid instead:

 orders = session.query(Order).all()
g = Grid(Order, orders)
print g.render()

Which results in:

Saving changes is similarly easy. (Here we're using Pylons-style request.params(); adjust for your framework of choice as necessary):

 fs = FieldSet(order1, request.params())
if fs.validate():
    fs.sync()
    session.commit()

Grid works the same way. More details in the documentation; start with Form generation.

To give FormAlchemy a try, just easy_install it. If you have any questions, Alex and I are often in both #sqlalchemy and #pylons on freenode. And of course there's always the mailing list.

Comments

Anonymous said…
Great work and nice quick tutorial. I tried FA when it was version 0.2 or 0.3 and it has come along way, i'm going to try it out on my next project.
Keep going and well done on a good job getting to a stable release!
Nick
Kumar McMillan said…
Hi Jonathan. That's pretty neat. Has anyone attempted to make an automatic admin interface (like Django's) with FormAlchemy? I've seen AdminPylon for SA and Pylons but I don't know of any others.
Kumar McMillan said…
er, I should say, a "full blown admin interface" since I know that at a low level this is what you already got FormAlchemy to do.
Noah Gift said…
wow, this is excellent news Jonathan. I can't wait to try it this weekend.
Jonathan Ellis said…
Kumar: sort of -- I will post about my mini admin app soon, but if you are impatient, check out FA contrib/admin.py in svn and read the comments at the top. It doesn't do everything django's does (in particular, it leaves permissioning alone) but it does give you customizable CRUD out of the box and is quite a small amount of code, so it's easy to build on.
Anonymous said…
You sayed you think ToscaWidgets are The Wrong Way to build web apps. Can you elaborate on that?
I am interested in your arguments since I have to make a decision to use Tosca or not.

Popular posts from this blog

Why schema definition belongs in the database

Earlier, I wrote about how ORM developers shouldn't try to re-invent SQL . It doesn't need to be done, and you're not likely to end up with an actual improvement. SQL may be designed by committee, but it's also been refined from thousands if not millions of man-years of database experience. The same applies to DDL. (Data Definition Langage -- the part of the SQL standard that deals with CREATE and ALTER.) Unfortunately, a number of Python ORMs are trying to replace DDL with a homegrown Python API. This is a Bad Thing. There are at least four reasons why: Standards compliance Completeness Maintainability Beauty Standards compliance SQL DDL is a standard. That means if you want something more sophisticated than Emacs, you can choose any of half a dozen modeling tools like ERwin or ER/Studio to generate and edit your DDL. The Python data definition APIs, by contrast, aren't even compatibile with other Python tools. You can't take a table definition

Python at Mozy.com

At my day job, I write code for a company called Berkeley Data Systems. (They found me through this blog, actually. It's been a good place to work.) Our first product is free online backup at mozy.com . Our second beta release was yesterday; the obvious problems have been fixed, so I feel reasonably good about blogging about it. Our back end, which is the most algorithmically complex part -- as opposed to fighting-Microsoft-APIs complex, as we have to in our desktop client -- is 90% in python with one C extension for speed. We (well, they, since I wasn't at the company at that point) initially chose Python for speed of development, and it's definitely fulfilled that expectation. (It's also lived up to its reputation for readability, in that the Python code has had 3 different developers -- in serial -- with very quick ramp-ups in each case. Python's succinctness and and one-obvious-way-to-do-it philosophy played a big part in this.) If you try it out, pleas

A review of 6 Python IDEs

(March 2006: you may also be interested the updated review I did for PyCon -- http://spyced.blogspot.com/2006/02/pycon-python-ide-review.html .) For September's meeting, the Utah Python User Group hosted an IDE shootout. 5 presenters reviewed 6 IDEs: PyDev 0.9.8.1 Eric3 3.7.1 Boa Constructor 0.4.4 BlackAdder 1.1 Komodo 3.1 Wing IDE 2.0.3 (The windows version was tested for all but Eric3, which was tested on Linux. Eric3 is based on Qt, which basically means you can't run it on Windows unless you've shelled out $$$ for a commerical Qt license, since there is no GPL version of Qt for Windows. Yes, there's Qt Free , but that's not exactly production-ready software.) Perhaps the most notable IDEs not included are SPE and DrPython. Alas, nobody had time to review these, but if you're looking for a free IDE perhaps you should include these in your search, because PyDev was the only one of the 3 free ones that we'd consider using. And if you aren