Reusable Django Apps and Forking
One of the things that drew me towards Django was the idea of being able to create reusable applications that would sit on my PYTHONPATH instead of copied across multiple sites. Coming from WordPress, the constant security updates that required me to revisit old projects began to drive me mad.
Trouble in Paradise
With some real world Django experience under my belt, I find myself re-using apps all the time, but not how I originally expected. A fair amount of my client work comes from building content management systems, so I started out building a generic app like flatpages but more extendable and a blogging app. I dropped them in my PYTHONPATH and started adding them to INSTALLED_APPS on my projects.
Over time, they evolved and improved, but they started to handcuff me. I started thinking things like, “This would be a great feature for Project X, but it would break Project Y.” I was worrying about backwards compatibility for one-off sites that were already done and paid for. When I started going back into those projects to make them handle new versions of my application, I realized I was right back where I started with WordPress.
Use the Fork
Since then, I’ve started forking many of my apps for individual projects. While at first I thought I was losing all the benefits of reusable apps, I quickly realized they were still there. I can still get a site up and running rapidly by reusing open source and personal code libraries/applications, but now I have the added benefit of being able to customize them to my heart’s content without worrying about past projects. Things that improve the app go into the main repository for reuse in the next project.
Move On
But what about those once great projects that are now running on “legacy” code? Well… I’ve learned to walk away from them. DHH had a great post recently, All code will eventually go stale. It is true and it is OK. It means you’re learning and improving your craft. Unless I have some amazing new feature for the project or changes are requested by the client, I don’t touch it. If I do need to revisit it, a simple diff usually gets it up to date very quickly. I fix what I need to and leave the rest.
For apps that are polished and have a stable API, PYTHONPATH is often the best place for them. Don’t let it handcuff you though. If you need/want to make changes that don’t make sense in the global context, fork off a copy into your project and move on.
Disagree with me or have a different approach? Leave a comment, I’d love to hear about it.
Reader Comments
Got something to say?
This was written on April, 4 2008 and is filed in code, django.
Our Products
Categories
- portfolio
- code
- software
- company news
- trailmapping
- SEO
- wordpress
- presentation
- accessiblity
- subversion
- django
Archives
Elsewhere
What I’ve been up to online
-
Ever wanted to develop a real estate site, but didn't want to deal with the nuts & bolts? Now's your chance: http://premsites.com/developers
3 days, 6 hours ago # -
Core Shutdown
3 days, 13 hours ago # -
BackwardsIncompatibleChanges is my new best friend http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges
2 weeks ago # -
@mtrier You'll be lucky to find good snow in Colorado or much of North America that early. Most resorts open around the end of November.
2 weeks, 2 days ago # -
My analytics account magically started working agiain today. Thanks lazy web. "A List Apart" link love! http://tinyurl.com/6r7oas
2 weeks, 6 days ago # -
Since I started using GAFYD, my Google Analytics account no longer works and Google won't respond to my emails. suggestions?
3 weeks ago # -
@twiderrific you have my vote for staying local
3 weeks ago # -
Django snippets: Super User Conditional Page Exception Reporting
debug page for superuser, 500 for everyone else
3 weeks, 6 days ago # -
Anybody want to split a hotel room for #DjangoCon?
4 weeks ago # -
Just got confirmation I'm on the invite list for #DjangoCon. Being a member does have its benefits. Couch surf or hotel?
4 weeks ago # -
Admin Image Widget
4 weeks ago # -
Follow @trailmapping for Trailmapping.com updates. Just pushed some slick jQuery into production tonight.
4 weeks ago # -
Munin :: com :: djangoproject.com :: trac_tickets
Graphs of trac tickets for Django
1 month ago # -
Automating tests in Django | Eric's Site
Generate tests by simply clicking through your development site.
1 month ago # -
Creator/updater fields for admin
1 month, 1 week ago #


What about creating a new branch when you need to fork an application? It will then be easier to exchange patches back and forth between the generic application and the customized one.
That’s exactly the same conclusion I came to. I started building re-usable apps for a bunch of clients that were very similar (academic departments), but each department wanted small changes, so I ended up installing site-specific versions of the apps. I roll good, general-purpose changes into a master copy of the app, which I use to start new projects. It’s been the smoothest way to get the benefits of both.
Very good ideas, and makes a lot of sense for some things I’ve been working on. I think for these “generic” apps, using version control is ideal. I’m thinking that in the app’s trunk would be the standard, generic version. Then create a branch for the customized version. The apps could then be included in the custom project via svn:externals. And having branches would allow me to make major bug fixes, if they arrise, in trunk and roll them into the branches.
I like the idea of branching these out of a main repository. I need to brush up on my subversion commands, I haven’t used branches or external repositories much in the past. Maybe this would be a good time to learn git (or mercurial, or bazaar).
Thank you for very useful topic. Could you please provide some kind of code examples or may be pseudo-code examples to describe these 2 situations when it is needed to split solid application into 2 separate or not to split. What is the main reason for splitting?
For example I going to write cms. Do I need to develop these applications separately: authorization, categories management etc ?
The post is spot-on, and a good DVCS is really going to help you in that.
My choice the second one you mention: Mercurial.
It saddens me a bit when I see some Pythonista going to the wasteful complexity of git, and forgoing the jewel that Mercurial is.
Bazaar, yes, it’s workable, but not as well thought out. Its only advantage over Mercurial is its ability to push changes to Subversion repositories: but it’s not needed for your own work, and it’s going to be added to Mercurial soon anyway.
Some more details:
Mercurial 1.0 released
http://lwn.net/Articles/274823/
Also important, the book is a joy to read:
Distributed revision control with Mercurial
http://hgbook.red-bean.com/
Peter: You are right, ditch Subversion for this type of thing. You can easily import svn to git/bzr/hg, and the latter tools make adhoc branching child’s play, while with Subversion it’s the work of devils (you have to use additional tools, and you really have to decide on your merge strategy beforehand, and good luck if you choose wrong).
Sometimes when an app is well done and thought it gets quite easy to tweak without touching the actual app code. For example registration view methods accept templates, classes and other flexible joints as parameters.
The more we separate from the generic track,the more writting your own branch become a need.
@coulix, I agree with you that when possible, a generic app that handles most use cases is best, but it just doesn’t always work out that way.
@peter, I completely agree with you when you are working with someone else’s project. BUT when you’re building your own project I do think you can follow some of the django best practices and create a somewhat easily extensible api.
James Bennett’s pdf from pycon gets into some of the high level details. here’s the link: http://www.b-list.org/weblog/2008/mar/15/slides/
I do think model inheritance will play a role in taking this a step further, and then combining james’s notes – you pretty much have a lot of flexibility.
Don’t get me wrong here guys. I’m all for best practices, generic applications and extensible APIs.
My point here is that frameworks like Django are about rapid application development. If you find yourself spending significant time on APIs that you may use in the future, I think you are wasting time. Read It’s a problem when it’s a problem for a better description of what I’m getting at.
While I always keep in mind preparations for the future, I develop for the now. Tackling obstacles is best done when you know what they are not when you are speculating before you’ve even started. Sure, I take a step back and look at the big picture, but I don’t let it stop me from moving forward. I see a lot of projects get stalled in the planning phase because of “what ifs…” IMO, you’re better off to develop using concrete requirements and then get into a “Release early, release often” cycle.
I have yet to encounter a situation where I’ve had to significantly backtrack because of this technique. Well designed code (the kind that Django basically forces you into) should allow you to change paths and correct as you go with little difficulty.
@peter, a valid response indeed. I don’t disagree with you when it comes to building out projects for clients. don’t waste time over thinking the “maybe” or “wouldn’t this be great” ideas, aka developer scope creep (where a developer creates his/her own unrequired “requirements” and thereby extends the development cycle and introduces greater complexity).
but when it comes to building an app for the open source community, I do think, if it lends itself to “customization” opportunities then the developer should plan ahead to make it extensible where they can.
even still, I think we’d be foolish to expect whatever app is delivered to be completely free from “forking” options. if you try hard enough you’ll find a reason to “fork” any app. the best I can do…is try to reduce where applicable.
Kevin, we’re in agreement :)
Thanks for putting this in words, some validation that it makes perfect sense. Unfortunately now I have to learn git, not in the mood.
It should be possible, to some extent, to import a base application inside your application, and then just add specific custom bits required for the current project.