A Django-Style Admin Interface For Pyramid

pyramid-positive

pyramid_formalchemy provides a CRUD interface for Pyramid based on FormAlchemy. Which is to say it looks at your SQLAlchemy models and automagically generates an HTML interface to create, read, update and delete instances of those models from the database, very much like Django’s admin interface. That sounds pretty cool, doesn’t it? In this post I will demonstrate how to get it up and running and then start customizing the forms.

blogpost_formalchemy1

The Pyramid FAQ suggests you use pyramid_formalchemy if you want a Django style admin interface for Pyramid. I tried it and found that while the documentation is terrible it looks like pyramid_formalchemy could be a good way to do this. It didn’t come out perfectly straight away, and it took some detective work to figure out how to customize it at all, but it looks like it’s actually quite easy to customize in any way you would like.

There’s also fa.bootstrap which looks nice, and I think is based on pyramid_formalchemy, but I didn’t try, and I’m not sure what the license is.

A Quick Introduction

I will create a toy Pyramid app that I can use to keep track of which rock climbing routes I’ve climbed. This will involve first setting up a Pyramid app with sqlalchemy and pyramid_formalchemy, and then creating a sqlalchemy model class to store the info in the database, allowing pyramid_formalchemy to provide the forms to add and edit the information. So following along with the pyramid_formalchemy docs:

Create The App And Get It Up And Running

[sourcecode language=”bash”]
$ # create the python environment and install necessary packages
$ mkvirtualenv formalchemy
$ pip install six
$ pip install pyramid_formalchemy
$ pip install pyramid_fanstatic
$ pip install fa.jquery
[/sourcecode]

that’s

pyramid_fanstatic

, not

pyramid_fantastic

. . .

[sourcecode language=”bash”]
$ # use Pyramid’s pcreate to start a Pyramid app with sqlalchemy scaffolding.
$ pcreate -s alchemy rockclimber
[/sourcecode]

as the docs say, update setup.py to add

'pyramid_formalchemy'

to

install_requires

[sourcecode language=”bash”]
$ # now add the pyramid_formalchemy scaffolding
$ python setup.py develop
$ cd ..
$ pcreate -s pyramid_fa rockclimber
[/sourcecode]

as README_FORMALCHEMY.txt says, add

config.include('rockclimber.fainit')

to rockclimber/init.py:

main()

[sourcecode language=”bash”]
$ # a missing dependency apparently
$ pip install couchdbkit
$ # run Pyramid’s autogenerated db initialization script to create a sqlite db and tables.
$ initialize_rockclimber_db development.ini
$ # run the development web server
$ pserve development.ini
[/sourcecode]

visit localhost:6543/admin

blogpost_formalchemy1

and woo! that’s pretty fancy! the dummy MyModel class that the alchemy scaffold creates is available to CRUD.

Add My Own Model

So now it’s time for my rock climbing route model.
add to rockclimber/models.py

[sourcecode language=”python”]
from sqlalchemy import Boolean, Date

class Route(Base):
”’
A SQLAlchemy model class that will persist in the database
all the information about a rock climbing route that I want
to keep track of.
”’
__tablename__ = ‘routes’
id = Column(Integer, primary_key=True)
name = Column(Text)
rating = Column(Text)
guidebook = Column(Text)
route_type = Column(Text)
is_indoor = Column(Boolean, default=False)
location = Column(Text)
date_climbed = Column(Date)
climbing_partners = Column(Text)
is_lead = Column(Boolean, default=True)
notes = Column(Text)
[/sourcecode]
[sourcecode language=”bash”]
$ # recreate the database, and restart the web server
$ rm rockclimber.sqlite
$ initialize_rockclimber_db
$ pserve development.ini
[/sourcecode]

blogpost_formalchemy2

nice! So that was easy. There are a couple of things wrong with this though, the dates months are weird and it would be nice to have Route Type be a select.

Add A Select Input And A Better Renderer For The Date

One of the files created when the pyramid_fa scaffold was run was called faforms.py. If we make that file look like this:

[sourcecode language=”python”]
from formalchemy import forms
from formalchemy import tables

from rockclimber import models

class FieldSet(forms.FieldSet):
pass

class Grid(tables.Grid):
pass

route_type_options = [(”, ”), (‘boulder’, ‘boulder’), (‘sport’, ‘sport’), (‘trad’, ‘trad’)]
# Create a specially named instance of FieldSet that pyramid_formalchemy will find and use for
# the Route model.
Route = FieldSet(models.Route)
Route.configure(
options=[
Route.route_type.dropdown(options=route_type_options),
Route.date_climbed.date(),
]
)
[/sourcecode]

blogpost_formalchemy3

then we get a dropdown for route and avoid the month problem by using a different renderer for date altogether. There’s still a problem with the dropdown where the current value isn’t selected when you edit the model though.

So there we have it. You should take my solution for the dropdown and date rendering with a grain of salt as I’m not by any means an expert. This did seem to me to be the way you’re supposed to do it because the scaffold creates the faforms.py and then the pyramid_formalchemy views.py does this sort of thing:

[sourcecode language=”python”]
350 @actions.action()
351 def new(self):
352 fs = self.get_fieldset(suffix=’Add’)
[/sourcecode]

and:

[sourcecode language=”python”]
231 def get_fieldset(self, suffix=”, id=None):
232 """return a FieldSet object bound to the correct record for id.
233 """
234 request = self.request
235 model = id and request.model_instance or request.model_class
236 form_name = request.model_name + suffix
237 fs = getattr(request.forms, form_name, None)
238 if fs is None:
239 fs = getattr(request.forms, request.model_name,
240 self.fieldset_class)
[/sourcecode]

which is to say that on Add it first looks for an instance of a FieldSet named

RouteAdd

in faforms.py and then, if it fails to find that, for an instance of a FieldSet named

Route

in the same place, before using a default

FieldSet

.

Would I Use This For Real?

So, the documentation is bad. I couldn’t find a bunch of tutorials or articles about it when googling for help, and some of the stuff I did find was out of date. The FormAlchemy google group I found had posts mostly between 2007 – 2012 (although more recent posts did have responses) which suggests it’s not currently very actively used.

pyramid_formalchemy

last got a commit in April 2013. There’s an obvious glaring problem with the out of the box date renderer.

On the other hand pyramid_formalchemy and FormAlchemy seem mature and fully featured. It was quite easy to get up and running and quite easy to customize once I understood what I needed to do. I was able to create a useful app in a couple of hours (even with all the googling) typing very few lines of code. Which is awesome.

I plan on using it again. Have you tried (and perhaps had better success with?) any other packages that solve this problem?

Tags:

Creative Commons License

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.