Banjo Six Months Later
Banjo is a good foundation for a blog engine, but it needs some work. It is
certainly quicker to implement than writing your own blog engine, but it is not
as finished as I had hoped. I fixed a number of bugs, and the banjo maintainer
was nice enough to give me write access to contribute my changes back. However,
my goal was to work with a community where I could learn from experienced Django
developers, and there isn’t much of a community around Banjo right now.
Discovering Byteflow
When fireant came across my blog post on Banjo,
he asked me why I wasn’t using Byteflow. My answer was that I had not heard of
Byteflow. I started looking into it, and it looked like a good alternative to Banjo.
My first impression of Byteflow was very similar to Banjo: lots of features,
lots of potential, but it looked like a dead project. The server wasn’t
responding well, the homepage news was out of date, and the mailing lists were
full of spam.
Then I looked at the IRC logs and found an active community that mostly speaks
an Eastern European language (Russian or Ukrainian, based on the location of the
authors). When I asked a couple of questions in English, I got very friendly and
helpful responses from piranha, the main Byteflow author. Not only are the
Byteflow developers active, but they are open to contributions. I helped clean
up the newsgroup spam, and updated the homepage to reflect the release last
spring. And as I adapted Byteflow to the specifics of my installation, they
accepted my patches and got them into the code base in the same day.
So far Byteflow has exceeded my expectations. Not only has it been a reliable
blog engine (for the last two days anyway), it also incorporates many of the
features I was hoping to implement* in Banjo. Most of all, I’ve been learning a
lot from working with the Byteflow developers (piranha already showed me a few cool
Mercurial tricks). That is my biggest justification for spending time on a
Django blog instead of using a mature product. I’ve been the only tech guy at my
family startup for the past year, and I’ve needed to find a project where I can
keep my skills fresh by working with others.
* I’m finally an OpenID provider! After almost ten years, I signed up for a
Slashdot account just to test it out.
Setting up Byteflow
This week I had two free days between work projects, so I decided to migrate my
blog to Byteflow. The installation went very smoothly—the best I have
experienced with a Django app.
Dependencies
Byteflow has no dependencies that needed to be filled outside of a typical package management system.
Base (all from Aptitude):
- Debian Lenny
- Postgres
- Django 1.1 (1.0 should work)
- Python 2.5.2
- Apache
- mod_python*
* I’m convinced that I should switch to mod_wsgi, but Byteflow works fine with
my existing mod_python install.
From Aptitude:
- python-psycopg2 2.0.7-4
- python-openid 2.2.1-2
- python-beautifulsoup 3.0.7-1
- python-imaging 1.1.6-3
Installation
In the past the Byteflow project has announced releases, but I don’t see them
packaged for download anywhere. It would be preferable to have a known
functional configuration. Since it has been a couple of weeks without a series
of commits to the Mercurial repository, I decided to have faith that it’s in
working condition and I cloned the repo.
hg clone http://hg.piranha.org.ua/byteflow/
It is a small repo and a clean codebase. Everything worked out of the box by
copying settings_local.py.template to setting_local.py, editing it to point to a
clean database, running syncdb, and pointing Apache to the Byteflow settings.py.
The default template came up, and a test post through the admin interface appeared.
Very easy, very slick.
Configuring Byteflow as an App
I like to keep code maintained by other people strictly separate from code I
maintain. It was as easy to do that with Byteflow as with most Django apps, but
did require some tweaking. The basic idea is to keep Byteflow in my
shared_django_libs directory (I’ll call this PROJECT_ROOT), and have the apps
Apache sees in a completely different directory tree (I’ll call my personal site REPO_ROOT).
I’ll define a couple of variables to make this easier to follow:
- PROJECT_ROOT: my clone of the Byteflow repository.
- REPO_ROOT: the repository where I keep my site.
- WEB_ROOT: the Apache web root where I keep static files, .htaccess files, and
other stuff serve-able by Apache. The location is REPO_ROOT/WEB_ROOT.
- STATIC_ROOT: the directory where Django serves static files. The location is REPO_ROOT/WEB_ROOT/static.
- STATIC_URL: the URL where Apache can see static files. It is SITE_NAME + ‘static’.
- MEDIA_ROOT: The Byteflow settings.py differentiates between media files and
static files. I treat them the same, so my MEDIA_ROOT = STATIC_ROOT.
- MEDIA_URL: As described above, my MEDIA_URL = STATIC_URL.
- SITE_ROOT: the directory containing my settings.py and other local Django
code. It’s at REPO_ROOT/SITE_ROOT.
- THEMES_DIR: The directory where my local themes live. It is SITE_ROOT/THEMES_DIR.
- Copy the default settings.py into your app (not settings_local.py).
- Edit your settings.py as follows:
- At the top of the file, just before the lines where it adds ‘apps’ and
‘compat’ to the sys.path, set PROJECT_ROOT to point at your byteflow install.
Then add this line:
sys.path.insert(0, os.path.join(os.path.dirname(PROJECT_ROOT)))
- Add variables for SITE_ROOT and WEB_ROOT. Then use those variables to define
STATIC_ROOT, MEDIA_ROOT, and THEMES_DIR.
- Remove the loading of settings_local.py.
- Create a file containing your SECRET_KEY, and point your settings.py to it (I
used the SITE_ROOT variable).
- Add these lines at the bottom of your urls.py, where it can catch any URLs
you don’t already deal with:
import byteflow.urls
urlpatterns += byteflow.urls.urlpatterns
- Copy from PROJECT_ROOT/static to STATIC_ROOT these directories: css, img, js.
That’s all I remember it taking. Now Byteflow plays happily with everything I’m
already running.
Creating a Custom Theme
Of course the default theme doesn’t look like _my_ ugly blog. To get my
distinctive look, I had to create a custom theme. It took a while to get
everything looking right, but the process wasn’t really difficult. It mostly
involved me merging the important parts of Byteflow’s default base.html into my
existing template, and looking at the other Byteflow themes to figure out how to
make changes to the Byteflow pages.
- In THEMES_DIR, create a directory with the name of the theme you specified in
your settings.py
- It needs a base.html in that directory. My base.html includes the contents of
PROJECT_ROOT/templates/base.html, header.html, and footer.html.
- You can over-ride any template in PROJECT_ROOT/templates by having a template
with the same name and directory structure in your theme. For example, I changed
the way a blog post looks by copying post_entry.html from
PROJECT_ROOT/templates/blog into THEMES_DIR/my_theme/blog, and editing it. You
can also override templatetags by copying them from
PROJECT_ROOT/templates/templatetags into THEMES_DIR/my_theme/templatetags. I
changed the way the dates looked by stealing the datelinks,html from one of the
included Byteflow templates. (Thanks for the tip on that one, piranha.)
- Create a directory in STATIC_ROOT with your theme name, and then you can
override the contents of css, img, and js. Took my existing CSS file, called it
main.css, and then added a couple of entries to change the look of Byteflow
generated elements.
Importing the Data from Banjo
Since I only had 30 or so posts to migrate, I figured I’d just do it by hand to
gain experience with Byteflow’s interface and the various markup languages. It
also gave me the chance to correct some typos and formatting problems introduced
during the last two migrations and the use of Banjo’s unpredictable markup
engine. Though I fixed a lot, unfortunately I suspect I added some new typos.
Before I installed Byteflow, I did a pg_dump on my blog database. Then I dropped
and recreated the database for Byteflow. I then used that dump to enter each
post through the Admin interface.
I couldn’t bear to lose the comments on my previous blog (all two of them), but
the Admin UI doesn’t allow comment creation. So I submitted the comments through
the blog interface, and edited the DB to have the original timestamps.
Unbeknownst to me, Byteflow sent out an email for each comment alerting the
original submitter that they had just created an account on my site. One of them
contacted me, worried about being blamed for something they didn’t do. If you
decide to do a similar migration, disable Django’s email sending ability until
you complete the migration.
Problems with reStructered Text
I couldn’t use reStructured Text out of the box. I was getting weird errors that
perfectly matched the bug reported here:
http://code.djangoproject.com/ticket/6681
The workaround discussed there worked for me. All you need to do is comment out
this line in django/contrib/admindocs/utils.py:
docutils.parsers.rst.roles.DEFAULT_INTERPRETED_ROLE = 'cmsreference'
With that change, a was able to use reStructured Text on two posts, but the
third had strange docutils errors showing up in my page. I didn’t have time to
turn that in to a reproducible bug report, so I just switched to Markdown.
Impressions
Banjo features not in Byteflow
There are a few things I preferred in Banjo:
- Byteflow has no concept of a “Post Summary” and a “Post Excerpt”. The entire
post shows up on the home page. I prefer this, but some people might not.
- Byteflow has a good tagging engine, but it has no concept of hierarchical
Categories. Personally, I like Categories better than tags, but I’m willing to
live without them for now (I’m emulating them with tags).
- Byteflow has no concept of a post update time. This also doesn’t bother me, but some might care.
- Byteflow can not configure the URL to a blog post in the same way as Banjo. I
set Banjo up to by YYYY/slug, but byteflow insists on YYYY/MM/DD/slug. Given how
rarely I post, I don’t need such a complex URL structure.
Best things about Byteflow
There is a lot to praise, but at the top of my list is the very helpful
developer community (as represented by piranha). I appreciated their willingness
to accept my patches and allow me to contribute.
The code is well organized and easy to modify.
I also like the way it handles comment spam. When a person posts a comment, a
site account is automatically generated and an email is sent to the comment
author. The comment is not viewable until it has been approved by either the
site administrator or through the email sent to the comment author. In the
future the author can log in to post without needing any moderation. This scheme
should eliminate the majority of comment spam which is produced by people using
non-legitimate email addresses. However, anonymity is sacrificed. I’m not sure
if I prefer it to reCAPTCHA—that will take some thought.
Annoyances
There are a couple of design decisions that bother me a little bit, like the
lack of admin control over comments and how subscriptions are handled, but these
are pretty minor.
I worry about having problems with my data during upgrade, but the author is
working on South integration so I’m hoping that is addressed soon.
The Byteflow.su project server responds to me only intermittently, but I’m starting to suspect it’s DNS related and might be on my end.
I’m not sure I understand the authentication system. The default template has
some buttons related to authentication that mystify me (“Close”?). But it
appears to be working okay.
On the whole, I have very few annoyances with Byteflow. The only big one I had
(not being able to store themes outside of the byteflow root), was quickly
addressed when they incorporated my patch.
Conclusion
As usual, the migration took longer than I expected, but it was less than two
days of work (including research into Byteflow, documentation work, contributing
changes back, playing with the CSS of my theme, and importing data). Manually
importing and formatting posts took half of a long day. A clean setup without
all the additional activities would take just a couple of hours.
I like how the Byteflow authors run their project. The pace of development has
slowed recently because piranha is happy with the current feature set and has largely
moved on to other projects. However Byteflow is not abandoned; piranha still
uses it as his primary blogging platform. Since he is readily available on IRC
and active on the mailing list, it is easy to discuss the architecture with him
and make contributions. I am betting that I’ll be happy with Byteflow for a long
time to come.