Django has proven itself (to me, anyway) as a great tool for the job of creating very robust web applications with lightning speed. In just a week or two, I’ve created a site that encompasses a blog with an akismet-powered comment moderation system, a code sharing section complete with highlighted code segments (and line numbers), and I have a way to create static HTML pages and map them to whatever URL I want. Behind all of this is an administrative area where I can add/edit/delete any type of content hosted on the site, add users, put them in groups, and even create new sites, and map content to the different sites. It’s pretty powerful.
One thing I really like about Django is that it lets you be sort of a commitment-phobe, and actually rewards you for it. If you’re not sure which direction you want to go in with a given feature, just make it as generic as possible. Not sure which URL you want some content to show up at? No problem — edit a line in the project’s URLConf, and it’s somewhere else now. Need to redo that sidebar menu to pull in content from a completely new app? No problem. Edit a template with a couple of new tags, delete some others, and if you’ve set up inheritance properly, that’s it. Done. Decided you want users to be logged in to see some content? Multiple ways to do that – edit the view, edit the template… easy, easy, easy.
And did I say powerful?
However, with great power, of course, comes great responsibility. One thing I don’t want to do is create some monstrosity of code with tightly-coupled entities, because that takes away my ability to be non-commital and make on-the-fly changes with the greatest of ease. As it turns out, being non-commital takes a bit of thought, and a bit of work.
So here’s the deal…
I have a blog app which I think is extremely similar to the blog app in Practical Django Projects, 2nd Edition. It has an Entry object which has some rather nice features that I think are generically useful regardless of whether this “Entry” happens to be a blog post, an article in a CMS, a code snippet, or whatever. And this is the root of my design dilemma.
I’d like to devote a section of my site to republished articles I’ve written over the years, and new ones I plan to write going forward. Having used Django’s built-in flatpages app for static HTML content, I can already see that it’s really not up to doing double-duty as a CMS. Specifically, it doesn’t have the notion of status, so I can’t mark something “Draft” and come back to it later. It also requires me to put in a URL to create a static mapping between a URL and a flatpage object. Also, flatpage objects don’t have attributes I’d like to have like “Original Publication Date”, “Original Publication URL”, “Last Updated”, etc. There’s no notion of categories, tags, or anything like that, either, which I think could be useful in presenting the list of available articles.
But my blog app has a good bit of that functionality, and my Entry object has a good number of the attributes I want. So where to from here?
Well, I haven’t looked deeply into this, but I know I could subclass Entry, make the one or two changes I’d need, and go that route. Unfortunately, doing this basically means that the CMS isn’t really “standalone”. It depends on my blog app.
The other option is to build the features I want *into* the blog app itself. I haven’t looked deeply into this either, but I don’t think it would be all that difficult to create a way for me to specify at the time I create an “Entry” that this piece of content is a “Blog Post” or an “Article”. However, at that point I’m basically turning my standalone blog app into something that is not just a blog app. If I ever built another site and only wanted a blog, I couldn’t just move my blog app into place and have it. Or… I could, but I’d have all this “Article” cruft hanging around in my admin interface.
This is all not to mention that I’d be breaking a tradition of keeping things small and simple, both to ease debugging, and to ease future development of the small, simple app. Everything becomes more complex. Maybe I’m answering my own question…
What to do?
I’m unsure which way to take it, to be honest. My thinking right now is that I’ll just copy my blog app’s models.py file to my new app, make my changes there in the new app, and ‘syncdb’. Sure, it’s redundant… but it’s only redundant *today*. If I decide later on to add a feature to the blog that makes absolutely no sense for the CMS (or vice versa), I win. If I decide to create a new site that only needs a CMS *or* a blog, I also win.
I’m always open to suggestions and bits of wisdom from folks who’ve been down this road before. If you see big gaping flaws in my logic, let me know. Otherwise, I’m gonna create some short-term redundancy in exchange for some long-term flexibility.