(Ab)using django in fun and interesting ways
Django is of course an excellent framework for building web applications. But since it’s quit modular, it is also possible to use only parts of it in non-web products. Being fed up with the cheetah templating engine (which basically reimplements python, and is no fun to use) and sqlobject (where’s the documentation?), I decided that for falcon I would use django’s excellent object-relational mapper and templating engine.
Since I made that switch, hacking on falcon finally became fun again and the next release (albeit beta) is imminent!
But no matter how nice django is, there are some caveats when you want to use and extend django the way I did.
- You need to call django.conf.settings.configure manually, so I ran into an interesting bootstrapping problem.
- Changing configuration later needs setattr()
- Using your own templatetags without actually having what django calls an application is actually simple, but you do need to know how it works: you need a folder foo/templatetags, where foo is in sys.path and in django’s INSTALLED_APPS, then put your tags in foo/templatetags/bar.py
- Automatically initializing database tables is not a feature. But since getting the creation statements is a feature and access to the database connection is another one, that problem can be solved by looking at the django code, this is how I did it:
from django.core import management
management.disable_termcolors()
all_models = (pocket.Component, pocket.MetaComponent, package.SourcePackage, package.BinaryPackage)
all_sql = []
for model in all_models:
sql, ref = management._get_sql_model_create(model, all_models)
all_sql += sql
cursor = connection.cursor()
for s in all_sql:
cursor.execute(s.replace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS'))
- Adding a new field type is surprisingly hard. Sqlobject has a PickleColumn, for which data is automatically pickled. I wanted to add this to django, without modifying django itself. After creating the field type (a subclass of django.db.models.Field), I only got errors. Adding a type mapping to what django calls the creation module, those errors were gone. Automatic pickling is also possible, if you override the get_db_prep_save function. But then it broke, since automatic unpickling is not possible, there is no ‘data thawing’ functionality in django. So I ended up letting the constructors of the models that use the PickleField do this.
After those things were solved, the excellent django documentation helped me write the rest of the surrounding code and falcon now is faster and better than ever. Now to fix the remaining bugs and then release it, it’s been too long since I made a release.
Can’t you use syncdb to create the tables for you?
I know it doesn’t alter or drop tables or anything, but it will create them if they don’t exist.
To run manage.py, you need a django config. I don’t have a django config (it’s configured at runtime)
why not sqlalchemy (which Django will eventually be using for its own ORM, if all goes well in the SQLAlchemy integration branch, if i recall correctly)?
I have to agree with your dislike for Cheetah, but if you want a lighter-weight more Pythonic templating language, there’s Mako (the successor to Myghty), or if you prefer sandboxed more django-like templates, Jinja (http://jinja.pocoo.org/) - no need to haul in the extra baggage of the fairly tightly coupled Django, and it might have saved you some of the bootstrapping hassles.
I’ve encountered the lack of “data thawing” in Django too. I think it’s just a bug rather than a missing feature.
I’ve reported it here:
http://code.djangoproject.com/ticket/6152