« links for 2006-07-30 | Main | That nobody else could do »

Django 0.95


Adrian Holovaty: "We're pleased to introduce Django release 0.95, a formal packaging of all of the significant advances in Django development since the 0.91 release in January 2006.". Some highlights:

  • Hooks for custom authentication
  • Optional modules decoupled 1 - they've always been optional, but up to now you had to build their tables.
  • Optional modules decoupled 2 - you can use stuff like django templates outside Django.
  • Use Django without a database - goods news for people like me, Tim Bray and the other 6 non-XML people in the world who think dbs are optional ;)
  • Database transactions

Full release notes are on djangoproject.com.

The main takeaway from this release is that the Model and DB APIs are crystallising fast - there will be some changes, but nothing like what's been going on in the last 12 months. That's good news for people who are considering deploying on Django or looking at it for production use, and 0.95 is definitely what to look at. If you are looking at Django and are put off by the "0.9" status - please don't be - it's in very good shape.

The rest of the post are my personal notes on what's improved since magic-removal was merged into the main line last spring:

No more magic imports

Old code:

   from django.models.website import newsentrys

Note how the module (your webapp) is imported via django.models and not your webapp's namespace. There's some serious meta-reflection type stuff going on there. It's cool stuff, but here's the problem - "newsentrys" is the name of the db table, not your object. That was entirely functional but seriously leaky.

New code:

  from website.content.models import NewsEntry

For that alone, upgrading is worth it.

Less framework cruft

Django never added much extraneous matter to your app code, and 0.95 trims it further. There are four python files to a site setup and each app is created with three files (both counts including _init_.py). It's really, really clean.

Cleaned up accessors

Old code:
   news_list = newsentrys.get_list(order_by=['-pub_date'], limit=5)

In fairness this keyword args style is a super flexible means of declaring criteria for view code. The thing is, we're not really dealing with the application models, we're accessing database rows with Python funny talk instead of SQL.

New code:

  news_list = NewsEntry.objects.all().order_by('-pub_date')

What's nice about this is that it's become about a thousand times easier to plug non db backends transparently into the API, or support multiple databases. This can act as a facade around Sparta for example; or ZODB. It means in the real world where you have to integrate with something other than your model's immediate tables, Django will have better support for that. Finally, the latter form is more readable - read both out loud and see for yourself. [If you don't think reading code out loud is important, don't try to debug code over the phone ;)]

Cleaned up Admin code

Admin code in your model is cleaner, there's less use of ((tuples,),).

Generic views

Jeff Croft sells this better than I ever could - generic views have lots of awesome points for people who want to build websites and not be programmers. Folks like Jeff are building home rolled weblogs almost entirely off the back of generic views. I'm thinking that they could be used to support the edit/introspection URLs we need for Atom Publishing Protocol. Every object in your webapp could be out of the box remote editable using APP aware clients, via generic views. Another upside to generic views is that they give you clean and stable URLs by default - most frameworks make you work for that, some go further and ensure you will have ropey URLs, unless you do an endrun around the framework.

No template name munging

No more magic file file extensions - 'news/index' in the code is no longer found at 'news/index.html' on the file system. It's a little thing, and other frameworks (Struts, Plone) do this, but I've never liked it, so I'm glad to see it gone. As of 0.95, when you have a "site-base.html" template, instead of declaring this:

  {% extends "site-base" %}

You say this:
  {% extends "site-base.html" %}

Not so good

RSS APIs. I've found the RSS APIs a tad awkward to extend, for example I had to patch to get proper atom support, you shouldn't need to do that. I think that's because the way the API works is you inject parameter values into a serialiser instead of pulling at it - if the field targets aren't there in the default data structure it gets tricky. I'm inclined to think that templates are a better way to generate feeds until this is reworked, but it's fair to say with my involvement in Atom, I'm prone to getting hung up on feed minutae. For most folks the inbuilt support will be just fine - at least Django actually has a way to emit RSS, which puts it way ahead of most frameworks.

Model Inheritence and One to One relationships. You can't subclass models and the committers have been warning us that one to one relations are going to change at some point. These are being actively developed, and didn't make it into 0.95.

Unicode and localisation. "Unicode Inside" is more or less there, kind of sort of, but it's inconsistent and you can get mildly bitten. Django is an internationalised framework, and localisation (l10n) for Django has grown well beyond Welsh at this stage, but, the .po files are not consistently generated or kept up to date, so some locales will pop up English strings now and then. I doubt the Django team will deal head on with l10n until after 1.0 when a freeze on strings might be reasonable. Every change in the code that alters or adds a user visible string affects the locale files which are just over 30 at the time of writing - that's the price of supporting internationalisation. Django builds a single .po file per locale for the core frame work and all contrib modules - true to its full-stack nature locale files are not broken out by module.

July 30, 2006 04:08 PM


Jacob Kaplan-Moss
(July 30, 2006 08:43 PM #)

Thanks for the great write-up, Bill.

I think I agree with you on all points, with the possible exception of the RSS API; I'm not sure I get what you don't like. Can you maybe give more details on what you had to hack around? I'd love to improve Django's RSS framework even further...

(July 30, 2006 11:45 PM #)

Hello Bill. I've been noodling for some time over how to address 4Suite's shortcomings as a web server (the server component, also called the respository) by possibly integrating it with an easy to use, pluggable, framework with support for HTTP features (such as session management, HTTPS possibly, URL pattern matching, submission processing, etc..). The whole python web app framework universe is quite daunting and that has been my primary deterent from trying any. The 3 I've looked the most closesly at are CherryPy , Django, and Aquarium.

My question (yes, I have one) is how much easier Django's recent modifications (it's another framework i've been looking at) make it to plug in 'non-convtional' APIs such as Sparta (which you mention in the above piece), RDFLib, 4Suite's Server / Repository (http://www-128.ibm.com/developerworks/xml/edu/x-dw-x4suite5-i.html), etc..

Ultimately I hope to have RDFLib (and derivative APIs such as SPARTA) work in tandem with the 4Suite repository APIs (for all content management requiremenets) and a third-party web app framework for the remaining web-related requirements: serving, session management, etc..

However, I'm less familiar with the state of the art with web app frameworks and wondered what your thoughts are with regards to Django and how you are using it with 'non-conventional' data APIs

(July 31, 2006 12:19 AM #)

Django without a database! Sweet. Have to look up the details on that.

Adrian Holovaty
(July 31, 2006 02:30 AM #)

Great entry, Bill. And, yeah, let us know how we could improve the feed syndication framework -- I agree that it's way too difficult to add arbitrary data to feeds. Let's fix that!

Parand: "Django without a database" simply means that the framework no longer requires you to have a working database set up just to serve dynamic pages. In other words, you can just use URLconfs/views on their own. Previously, the framework required that a database be configured, regardless of whether you actually used it. That was just a bit of cruftiness that I'm glad we've removed.

James Bennett
(July 31, 2006 05:13 AM #)

Well, I can't speak for Bill, but I did run into a few issues when I decided to do Atom feeds on my blog; for one thing, I think we need clearer documentation pointing out the things that Atom requires -- it took me four or five tries before I could get a basic Atom feed to validate.

But I think the root problems are twofold:

1. We're serializing to a hard-coded set of possible elements that doesn't always cover the things you might want to do. Templates at the level of 'item' rather than the level of 'title' and 'description' have been suggested once or twice, and feel like a good idea.

2. We're using the same basic data model for both RSS and Atom. That leads to difficulties when you want something that's clearly spec'd out in Atom but not in RSS (for example: I'd love to be able to do full-content Atom feeds, but we don't support atom:content and there's no clear winner for an RSS equivalent to put into the feed generator).

Simon Willison
(July 31, 2006 04:11 PM #)

I'm not too keen on the configuration part of the syndication framework - in my own code I've tended to use the low-level API instead, because I want to just hook /weblog/atom/ up to a view that produces Atom rather than bother with another layer of confiuration.

Of course, if we applied my callables-instead-of-just-strings patch to the URL handling part we could do much smarter things with hooking feed-producing functions directly up to URLs, no view string required :)

Bill de hOra
(July 31, 2006 11:58 PM #)

"I'm not sure I get what you don't like. Can you maybe give more details on what you had to hack around?"

Jacob, you're absolutely right to call me out. I'll try to write it up rsn and be less handwavy.

Bill de hOra
(August 1, 2006 12:30 AM #)

"My question (yes, I have one) is how much easier Django's recent modifications (it's another framework i've been looking at) make it to plug in 'non-convtional' APIs such as Sparta (which you mention in the above piece), RDFLib, 4Suite's Server / Repository (http://www-128.ibm.com/developerworks/xml/edu/x-dw-x4suite5-i.html), etc.."

Chimezie; prior to the magic-removal work, to meet the DBAPI contract 'transparently' it wouldn't have been enough to fill out the models by implementing Django's field types onto some storage. You'd have had to emulate the generated table mappings as well. As of 0.95 once you support the Model/fields, you're "done".

My first Django exercise was with pure RDF and it sucked not being able to leverage the great stuff you get via the field types - everything had to be handrolled. Of course you can store arbitrarily formed content as RDF, and incomplete/partial content but you have work to do to get that in and out of a web form - ie the bread and butter stuff of most webapps becomes harder. RDF isn't constrained enough for regular webapp work; the answer seems to be to support a type system that lets you build forms and validation engines 'for free'. I think Django's field types could be on the sweet spot, ie, I think they could be standardised on. By comparison I suspect the type/widget systems in Zope2/Plone are overly flexible and too difficult to support - they might not portable outside ZODB.

It's tricky; you have to sign up to supporting an RDBMS based set of types for core modelling and a means hook in property value extensions. To see where Django tries to hook in the kind of flexibility RDF provides right now, take a look at contenttypes:


Post a comment

(you may use HTML tags for style)

Remember Me?

Trackback Pings

TrackBack URL for this entry: