Office Resource Locator Ported to Django

After going through the Django tutorial, I decided to try how Django felt with a (small) real life application. I decided to port Solu (Self-service Office Resource Locator) – an application I originally wrote in Werkzeug.

Django-Solu gained two new features compared to the original: an administrator’s interface, and support for multiple maps. Administrators can add, delete and modify maps (as well as other resources), and when you create a resource you can select the map to put it on. There is no installable package, which is a regression from the original, due to the reasons described below.

At some level I was surprised how similar Django was to Werkzeug. For example, I was able to lift some unit tests and make just minor tweaks like changing a property name to get them to work in Django. There were also some very big differences, most notably in the database layer (compared to SQLAlchemy of which I have prior experience) and templates (compared to Mako Templates).

I can see how I can get stuff done in Django, but I was left puzzled with some pieces. Django seems to make a big deal about applications being self contained, so that (theoretically) you could create an app and anyone could download and install your app in their Django environment. Except this seems to fail a little bit with imports and templates, and spectacularly when dealing with static resources. Imports can be fixed by going through some hoops and modifying PYTHONPATH (which feels like a hack to me), templates by moving them inside the app directory (unlike what the tutorial instructs you to do) and calculating site root etc. in settings.py file (which isn’t actually one of the “standard” settings so you can’t rely on it), but I haven’t figured out any decent solutions for static resources. The problem with static resources is that I don’t know how to point to static resources from templates. Currently I just made these absolute paths, which may need to be edited based on deployment situation. Maybe there is a simple solution I am overlooking, since I can’t imagine Django being so popular with this kind of limitation.

The templates themselves kind of force you to not put any code in the templates, but this has in turn resulted in some bizarre constructs to work around the no code limitations. For example, the template language still allows you to do simple arithmetic with tortured syntax: my_variable|add:"-10" adds -10 to my_variable before printing it out.

The database layer was simple to work with, at least in my simple use case, although there was one point where I was stumped for a while. When searching for resources, I wanted to order the search results in certain way. But there does not seem to be a way to do that in the query syntax. Instead, you need to add a Meta class as a child of each model class and add ordering class attribute. I don’t see how this would work if you wanted to change ordering on the fly or if you have joins and want to order by attributes from different tables. It was also a little difficult to find this information about ordering.

All in all I spent 9-10 hours porting the application, which was roughly what I expected. I spent another 2 hours deploying a live demo application on Dreamhost, which was somewhat more involved than I expected.

Similar Posts:

    None Found

4 Comments

  1. James Bennett:

    I’m a bit confused as to your trouble with “imports” — Django applications are simply Python modules, live on the import path like anything else and should be importable like anything else. You *can* stick them elsewhere and do path hacking, but I don’t really know of anyone who recommends that (and though the tutorial stuffs an application inside a project directory in order to stay focused on Django and avoid the need to teach people Python basics like the import path, I’ve been campaigning for a while to change that).

    Media and templates are harder. The short answer is that I personally don’t think there’s such a thing as truly portable templates and media for public-facing parts of an application; backend logic is easy, but providing something which A) is good enough for cases where you can make it fit and B) easy enough to override in the majority of cases where you can’t is, well, impossible 🙂

    The long answer is that you can probably solve this by giving up on Python and instead doing everything through setuptools APIs, but I’m not a big fan of that.

    Also, you might want to look again at the database API documentation; what you found was simply a shortcut for declaring default ordering for queries on a particular model. The full API documentation lists the “order_by()” method of querysets, which is what you want for per-query ordering:

    http://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by-fields

  2. James Bennett:

    Oh, and missed one point about the template language: in general, it’s meant to be much more restrictive than other templating engines. What I’ve personally found is that if I’m writing a complicated piece of template code to work around a perceived limitation in the language, it’s often because I’m really trying to move application logic out into my templates, and I almost always end up refactoring to produce a much cleaner solution. YMMV, of course, which is why we don’t force you to use Django’s template system 🙂

  3. masklinn:

    Re media paths, using RequestContext will inject your settings.MEDIA_URL value in your templates (as {{ MEDIA_URL }}).

    For PYTHONPATH, how’s setting it so that you can “see” your urls a hack? (alternatively, you can use virtualenv, put the app you’re working on in your virtualenv directory and launch your servers & al from there)

  4. Heikki Toivonen:

    @James: I was assuming that I’d need to be inside the “mysite” directory to be able create apps with the manage script, which then makes imports of the form mysite.myapp. I know I can manually move myapp elsewhere and modify PYTHONPATH and the imports, but this feels like running through unnecessary hoops. But on second look, it seems like manage.py startapp takes two options (settings, pythonpath) that maybe let you do it without those manual steps.

    Thanks for the link to the queryset document; for some reason I had missed the existence of the whole document! No wonder I felt limited without seeing this.

    I know there is a school of thought that thinks templates should not allow any code to run because, well, they are templates. But in practice this seems to lead to hacks to work around this limitation (like the arithmetic example above). This reminds me of the Python “private” members: you indicate you think something is an implementation detail by starting the name with an underscore, but there is nothing stopping others from using it if they have to. I feel like templates should be the same: you should avoid putting code there, but when it makes sense to put some code in a template then please let me.

    @masklinn: Ah, I think you hit the nail on the head on that MEDIA_URL. Thank you! As for PYTHONPATH, I grant this is probably just a personal preference, but whenever my script or application needs to touch PYTHONPATH it feels like a hack. I prefer putting my things in site-packages, and deploying things in virtualenvs (which, ironically, modifies PYTHONPATH but I don’t mind since it is not in my script). But it seems virtualenv has a way to create bootstrap scripts so maybe this could lead to a nice way to deploy a Django app.