Adding Arbitrary Mods to LifeFlow
As part of my recent extensions to LifeFlow I ran into a handful of situations where I wanted to allow those deploying LifeFlow to have more flexibility, but without breaking their SVN checkout. Even for those who don't have any desire to track changes from SVN benefit from having a clean and predictable system for extending their deployment.
With this in mind LifeFlow now has an extensible mod system. The concept behind this is to allow someone deploying LifeFlow to pick-and-choose pieces of functionality with a minimum of additional overhead.
This article takes a look at two examples of using modules to extend LifeFlow in simple but powerful ways. The first is using StaticGenerator to create static files to help run LifeFlow on shared hosting or a low powered VPS.
The second example is using the mod system to add a new piece of dynamic blog context to your entries.
Using StaticGenerator with LifeFlow
If you are running on a shared host you may have a number of performance concerns about running Django, especially if your content gets unexpectedly popular. The static_files mod helps relieve some of that stress.
With it enabled each time you save a blog entry a static rendering of it is generated, along with updated copies of the front page, the tags page, and the article series page. This means that the large majority of your content will be served as static pages, including everything that is likely to get pounded during a surge (your content itself, the blog entries, will be available to people coming to your site even if Django is completely offline).
Lets take a look at turning on the static_files mod. You just need to add a few settings to your settings.py file:
# You may already have LIFEFLOW_MODS, is so then just add 'static_files' to it
LIFEFLOW_MODS = ('static_files',)
WEB_ROOT = "/folder/to/generate/files/in/"
Thats all it takes to enable a LifeFlow mod. Its really dead simple. Notice that there is a module named 'static_files' in the lifeflow/mods directory, and you pretty much have the idea of it: just stick a module in that folder (it can be a module with an __init__.py file, or it can be a simple python file), and then add the name of that module to the LIFEFLOW_MODS parameter. Thats it.
Okay, so I made a slight lie about there being no step two. It happens that for the static_files mod there is a step two, and its a bit of a doozy: you have to configure your hosting environment to check first for the static files before requesting a file from Django.
The details of doing this will vary depending on your specific setup. I will have another article on this topic in the near future, but for the time being you can look at the documentation for StaticGenerator which features a complete example for nginx. Most shared hosters (for example those using Dreamhost) will find themselves needing to modify a .htaccess file to configure Apache for their shared directories, and I am working on an entry covering that exact situation (deploying LifeFlow on Dreamhost). Anyone who wants to look further into this themselves could find many worse places to start than the ModRewrite documentation.
Extending Dynamic Blog Context
Now lets look at another example. One of the neat tools in LifeFlow is Dynamic Blog Context, which allows you to write formatted references in MarkDown without making the references yourself.
The stock library of these dynamic references is fairly helpful, but you may find yourself wanting something that isn't yet included (consider sending me a diff containing the change, and if its reasonable it will very likely get included). Maybe you want a piece of dynamic context that relates to a second application that you build yourself.
Lets hypothesize that you want to include dynamic context for the most popular downloads on your new Django app named downer. Lets also presume that the relevant model is downer.models.download, and that the download model has a custom manager named popular that returns items sorted by popularity.
Now we want to make a dynamic context that allows for [popular 1] for a link to the most popular download. Lets see how hard it is to make that happen.
Create a new file downer_context.py in lifeflow/mods. Open it up and add this code:
# lifeflow/mods/downer_context.py
from lifeflow.markdown import mdx_lifeflow as lf
setattr(lf, "old_make_syntax", lf.make_syntax)
def new_make_syntax():
syntax = lf.old_make_syntax()
def popular(entry, str, nth):
from downer.models import download
dl = download.popular.all()[nth]
return str % dl.get_absolute_url
syntax[(1, "popular"))] = popular
return syntax
setattr(lf, "make_syntax", new_make_syntax)
Then you would just need to go to your settings.py file and modify your LIFEFLOW_MODS setting to look like this:
LIFEFLOW_MODS = ('downer_context',)
And your new blog entries could could contain the new popular dynamic reference that we just created.
This isn't a particularly gorgeous way of extending the dynamic references, but the point here is mostly that you can create drop-in extensions to LifeFlow without the necessity of creating an entire new Django application.
Admittedly in many situations simply adding a customized Django app of your own crafting will be cleaner and more possibly more efficient (because it doesn't have to consider theoretical possibilities, it only has to handle what it actual handles). One of the intentions behind the simple mod addition to LifeFlow is to move towards making it a platform that can be customized and modified with little expertise in using Django or Python.
At this point I think it has a very flexible structure, which allows experienced users to come in and customize to their hearts content, but provides enough good defaults to be a usable piece of software for people who don't want to jump through hoops to get their blogging software to work.
I'd be interested to hear any feedback or suggestions for improvements.