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.