July 13 2011 by Nicole Foster
Last month we hosted the first talk in our new Caktus Lightning Talk Lunch series. We started this series to get together and learn about new projects, different applications, and interesting topics that the Caktus team has been working on. Lunch was provided from Buns in Chapel Hill and Mark Lavin gave the first talk.
Mark presented on django-selectable, a Django autocomplete app powered by jQuery UI. Similar to django-ajax-selects, django-selectable provides a framework to construct autocompleting text fields, but differs in a few key areas:
- jQuery's native autocomplete plugin is used, rather than the now defunct bassistance version
- A declarative, class-based paradigm is used for easily defining and customizing lookup sources. No more template propagation and inline JavaScript!
- A registration process, similar to the Django admin, is used to enable lookups
- Many-to-Many field support and multi-selection (via an editable deck list)
- Multiple selects (and combo boxes) can be added to the same page
You can find Mark’s slides for the talk here. Also, the source code for django-selectable can be found here.
And here are a few pictures from the meeting-


Everyone had a great time and we are all really excited to see what other interesting topics the team comes up with to talk about.
May 18 2011 by Nicole Foster

I am excited to announce that The Buddha site won two Webby Awards! It was built in partnership with Sonnet Media as a companion to The Buddha documentary directed by David Grubin that aired on PBS in April 2010. The site was built using Django to create a multi layered interactive experience to further explore the life and times of the Buddha.
The Buddha won both the People’s Voice Award and the Webby Award in the Religion and Spirituality category.
Congratulations to everyone who worked on the project and thank you so much for voting!
April 12 2011 by Tobias McNulty
I'm delighted to announce that the PBS companion website for The Buddha — a site that Caktus helped build using the Django web framework — has been nominated for a Webby Award in the Religion and Spirituality category! Online voting for the People’s Voice awards is now underway and we would appreciate you voting for the site and encouraging others to do so as well. You can also view the entry page directly here.
We appreciate your support and thank you for helping us honor this wonderful program!
March 25 2011 by Nicole Foster
I'm excited to announce that Caktus is launching its summer internship program. It is a 12 week paid position in our Carrboro, NC office. We're in driving distance from UNC Chapel Hill, NC State in Raleigh, and Duke in Durham, so students from all parts of the NC Research Triangle are welcome to apply.
We are looking for a web developer who enjoys working on a team and is excited to work on new and diverse projects. While working with us you will get to work on Django-powered web applications, learn about test driven development and other agile methodologies, perform front-end development in HTML, CSS and JavaScript (jQuery) and become familiar with Linux (Debian-flavor) desktop and server systems. Check out the full posting here.
If you'd like to spend your summer working with some great people on interesting projects please email us at jobs+website@caktusgroup.com with your resume and, if applicable, links to samples of code you have written. Kindly include a brief note describing why you would be a great fit for this opportunity.
March 15 2011 by Mark Lavin
We just got back from another fun and successful PyCon. While we didn't get to stay for much of the sprints we did get to spend some time in the Django sprint Sunday and Monday. Monday morning I was there early and I noticed a bit of confusion among the Django sprinters. While I'm not a frequent contributor I've participated a few sprints at previous conferences and local sprints with Caktus. I shared with them my experiences and it seemed generally helpful so I thought I would share them here as well.
If you've ever sprinted at a large conference like PyCon or DjangoCon you've probably heard the speech from the core developer's about contributing. It's always nice to hear but it still doesn't stop people from being unsure about what to do or where to start at the sprints. I'm here to tell you as another non-core developer it really isn't that hard or scary. Django is a big project but you don't have to know everything to be able to help.
Where to start?
To start you should always read the contributing guide. Once you've got the Django source code checked out you should run the test suite just to make sure you know how. Do you have to check out from SVN? No, you don't. There are mirrors on GitHub and BitBucket and you should used the VCS that you are most comfortable with. Just remember to generate your patches from the source root directory and in a format that's compatible with SVN.
How do I find a ticket?
There are a couple different strategies for finding a good ticket to work on. The list of Trac tickets can be intimidating especially if this is your first time working on Django. One way to find a ticket to work on is to find an area that really frustrates you when using Django. Last year at DjangoCon I focused on contrib.sites, contrib.sitemaps and formsets because there were more than a couple issues that I had come across recently working with them. Thankfully we were even able to fix #11418 and #11358.
Some tickets have patches and tests but haven't been reviewed. It's fairly easy to download the patch, apply it and see if it works. You should also spend some time looking to make sure everything works the way the patch submitter claims it works. Either way you should comment on the ticket with your results. Also, some patches are fairly old and won't apply cleanly, but updating the original patch is something else that's easy to do and can be helpful. One common example of this is the recent shift from doctests to unittests. A number of patches that had tests may not apply because they were doctests. Converting those patches to use unittests is another way to help.
Another strategy is to find tickets which have patches but need tests. You can easily filter the Trac tickets by 'Has Patch' and 'Needs Tests'. Writing the tests can help you better understand the underlying code. You might also want to write some patches and if so just filter by the tickets without patches. Here you might also want to filter on areas that you are most comfortable with such as the admin, forms, or ORM. Remember that you need tests with all of your patches and documentation for new features.
Can I change the tickets?
I say don't be afraid to jump in. There is nothing you can do in Trac that can't be undone. While you shouldn't re-open tickets closed by core devs, if there are bugs you can't reproduce don't be afraid to say so. Tobias and I spent over an hour working to reproduce a bug at the last PyCon. In the end we closed the ticket as 'could not reproduce'. Once we did that at least two other people commented in IRC that they had tried and couldn't reproduce it either, but hadn't commented or closed the ticket. So, if you spend time looking at a ticket, do everyone a favor and share what you did. When commenting or closing a ticket remember to always be respectful. Someone was kind enough to take the time to put in a ticket to fix or improve Django and we are all a part of the same community.
The last thing I'll add is that contributing to Django doesn't have to start or end at the sprints. Trac is always available if you have some time to look through tickets. I hope this helps some people get the confidence to write or check patches for Django. Happy sprinting everyone!
March 12 2011 by Tobias McNulty
I'm delighted to announce that we've just published another job posting for a Linux Systems Administrator at Caktus. The position will involve maintaining existing Linux servers, designing and building highly-scalable deployments, and assistance with Django deployment and development as time permits. This is a full-time position, with benefits, and is based out of our Carrboro, NC office (a short drive from Raleigh, Durham, and Chapel Hill).
For more information, follow the link on our careers page and let us know if you or someone you know might be interested in the position!
March 09 2011 by Tobias McNulty
PyCon 2011 Atlanta is just around the corner, and I'm proud to announce that Caktus is a gold sponsor at the conference this year! We sponsored DjangoCon in both 2009 and 2010, and this year agreed to extend that support to the Python community in general.
PyCon US is the annual gathering of software developers who use the open source, Python programming language. Django, our web framework of choice, is written in Python, so we use the language every day here at Caktus to create custom web applications and dynamic, content-rich web sites. Additionally, starting last year, we've put some of that knowledge to use extending and developing applications for the RapidSMS framework - a tool for creating mobile health and data collection applications that integrate web and mobile components (via SMS).
This year, the conference is being held March 9th through the 17th, 2011 in Atlanta, Georgia. We've grown a little since last year at this time; 7 Caktus team members—Colin, Karen, Mark, Mike, Calvin, Nicole, and myself—will be attending the conference. We're thrilled to be going again this year and hope to see you there!
We're currently looking for a Django developer to join the team, so stop by and introduce yourself if you or someone you know might be interested in the position!
February 09 2011 by Tobias McNulty
I'm pleased to announce that we just released a new Careers section of our web site here at Caktus. The section has been inaugurated with a new posting for a full-time Django developer position based out of our Carrboro, NC office (not far from Raleigh, Durham, or Chapel Hill), so kindly check it out and let us know if you or someone you know might be a good fit!
December 29 2010 by Tobias McNulty
I recently returned from a 6 week trip in Malawi, where I was heavily involved in the implementation and deployment of Project Mwana, an Information and Communication Technology (ICT) project focused on Maternal and Newborn Child Health (MNCH). The project is currently running as a pilot in both Zambia and Malawi. This post is a fairly technical overview of what the project does and the way in which it was developed.
The project aims to facilitate several things, including (a) secure delivery of HIV (Dry Blood Spot, or DBS) test results from the lab to health clinics by SMS, which we’ve named “Results160″ (b) appointment reminders for newborn children, or “RemindMi” (Mi = mothers & infants), and (c) free-text “chat” for health clinic workers and Community Health Workers, to strengthen communication and patient tracing.
Source Code
The source code for the project, which is based on Django and RapidSMS, can be found on GitHub:
I updated the developer setup instructions fairly recently, so, if you’re developer interested in this project or line of work, you should be able to get a local copy up and running without too much trouble. If you try and do have any issues, please let me know!
Team Composition
In Zambia, we have 2 on-going local developers, 1 temporary lead developer, 1 on-going local project manager, and 1 on-going project mentor. The team is similar in Malawi, except we have 1 on-going local developer, 1 temporary lead developer (myself), 1 on-going local project manager, and 1 on-going project mentor.
Development Workflow
For this phase of the project we adopted “git flow” to help guide our development workflow, and I think it was a big success (more below). See the following links for more information:
Code Organization
apps/ - we tried to separate functionality into separate Django/RapidSMS apps as much as possible.
backends/ - contains a RapidSMS backend for communicating with Kannel (an open source SMS gateway)
locale/ - translation files for Bemba and Chichewa
requirements/ - pip requirements files & corresponding tarballs (we found that checking in the tarballs was crucial for easily re-creating a development or production environment in low-bandwidth situations)
malawi/ - Malawi-specific configuration files & code
zambia/ - Zambia-specific configuration files & code
Settings Files
We took a strongly hierarchical approach to the settings files, to make it easy to share/override settings as necessary:
settings_project.py
\> malawi/settings_country.py
\-> malawi/settings_staging.py
\-> malawi/settings_production.py
\-> localsettings.py
\-> zambia/settings_country.py
\-> malawi/settings_staging.py
\-> malawi/settings_production.py
\-> localsettings.py
Each “sub” settings file simply imports from its “parent” at the top of the file, thereby allowing you to, for example, insert or append an app, add or remove a middleware, etc.
Apps
The project is divided up into the following main Django/RapidSMS apps: Results160 is implemented (mostly) in the “labresults” app, RemindMi in the “reminders” app, and the clinic chat in the “broadcast” app. The other apps support various pieces of functionality such as location management (”locations”), additions to the contact model (”contactsplus”), “stringcleaning,” and SMS printer integration (”tlcprinters”). I won’t pretend that they’re at all pluggable at the moment, but I’m sure that some of the more useful parts could be extracted & made independent, should the need arise.
Lessons learned
On the Malawi side, we learned a few things about building RapidSMS (or mobile health ICT projects in general) that I think are worth sharing:
(1) Regular meetings. Have quick meetings to review progress and plan next actions. Scrum type meetings really helped us review and quickly narrow down and fix things that we saw were not going too well before they became a problem.
(2) Pair Programming. Even though we were often pressed for time, pair programming proved very beneficial to the team and the project in general. Part of the mandate for the project is creating local capacity, and hands-on pair programming allowed for the newer or more junior local developers to both in gain a good overview of the codebase and learn from the more seasoned Python/Django developers on the team.
(3) Feature Branches. git-flow made them easy — which was key because we had two teams working simultaneously in two different countries (between which communication was difficult at times), and we wanted to share most of what we were doing while also shelter each other from potentially buggy commit of partially implemented features.
(4) Using a single code base for two deployments. It was difficult at times, when our two teams were changing different parts of the code and inadvertently breaking parts of it, but overall I think it was a big win & well worth the effort. We get the benefit of shared features & bug fixes, we don’t have to deal with maintaining separate forks, and it forces us to optimize our development workflow and make our code that much more configurable.
(5) Server environment. Get a public facing IP for your server and/or work location before beginning the implementation. We didn’t have one of these to start with in Zambia, while we did in Malawi. It makes life far, far easier for a number of reasons, including (a) it lets stakeholders get to the server (obviously), (b) it helps you be sure any connectivity issues are on the telco side, not yours, and (c) it lets you avoid corporate firewalls.
(6) SMS Gateway. If you have an SMS requirement, use Kannel. We started out with pygsm and our MultiTech modem would regularly get into a weird state where it was registered on the network & responded to AT commands, but no messages would come through. With other modems, the gsm backend didn’t delete messages from the SIM card, so it quickly filled up. After we switched to Kannel, we only had one case of downtime — and it was the RapidSMS route process, not Kannel, that was at fault. We also implemented the project on two different network carriers: Zain (now Airtel) via a GSM modem, and TNM (over the internet via SMPP). Kannel gave us a unified interface with which to interact with the two different backends. Kannel was also valuable as a “reference product” with which to test out the SMPP connection provided to us by TNM; as it turned out, when we couldn’t connect to it at first, the issue was on their end, not ours, and having a second opinion to back up our suspicions was key.
For more information, please see our page on Project Mwana or get in touch with a member of the Caktus team!
September 24 2010 by Tobias McNulty
Sometimes, when building a web application in Django, one needs to connect to a legacy database whose tables already exist. To support this use case, Django has the concept of "unmanaged models," which let you connect the Django ORM to tables that it assumes to exist (and not attempt to create).
This can make automated testing---which is something we take seriously at Caktus---rather difficult, because you might not have the SQL on hand to create an empty copy of the legacy database for testing purposes. One solution is to automatically set all your unmanaged models to "managed" during a test run, so that Django will happily create the tables for you. Typically this is enough to allow you to add sample data to the database and write tests as you would for any other model in Django. We've also found the approach to work especially well for database views (which typically are manifested as unmanaged models in Django), because it may be easier to test the code that uses the view by treating it as a table during automated testing.
There's a great snippet available for doing this, but the code is lengthly and and basically requires copying and pasting a large portion of the existing test runner in Django. Django 1.2, however, introduces a new class-based test runner that's much better suited for small modifications to the testing process like this.
To give it a try, I wrote a short piece of code that accomplishes this---making all unmanaged models in your Django project "managed" for the duration of the test run:
from django.test.simple import DjangoTestSuiteRunner
class ManagedModelTestRunner(DjangoTestSuiteRunner):
"""
Test runner that automatically makes all unmanaged models in your Django
project managed for the duration of the test run, so that one doesn't need
to execute the SQL manually to create them.
"""
def setup_test_environment(self, *args, **kwargs):
from django.db.models.loading import get_models
self.unmanaged_models = [m for m in get_models()
if not m._meta.managed]
for m in self.unmanaged_models:
m._meta.managed = True
super(ManagedModelTestRunner, self).setup_test_environment(*args,
**kwargs)
def teardown_test_environment(self, *args, **kwargs):
super(ManagedModelTestRunner, self).teardown_test_environment(*args,
**kwargs)
# reset unmanaged models
for m in self.unmanaged_models:
m._meta.managed = False
Enjoy! Don't hesitate to comment with any questions or concerns.
September 03 2010 by Tobias McNulty
I'm delighted to announce that Caktus is looking for two Python and/or Django web developers to join our team on a contract or part-time basis, with the potential for full-time work in the future.
Caktus builds custom web applications for local and remote clients using a variety of open-source technologies. We are a small team based in the Chapel Hill/Carrboro area of North Carolina (currently residing in Carrboro Creative Coworking). We believe in face-to-face contact, both with clients and amongst ourselves, and employ agile development techniques that emphasize teamwork and collaboration. We encourage you to meet the team and learn more about what we do.
We're looking for two experienced Python and/or Django web developers who enjoy working on a team and are excited to work on new projects. We have a preference for local candidates, but will consider all submissions. Your work will involve creating and integrating Django apps, working on existing Django projects, deployment, and database work.
You will be working in Linux (Debian-flavor) production environments with Apache and WSGI. Python and relational database experience is required. Django experience is a (big) plus. HTML/CSS and JavaScript experience are also a must, and jQuery is a plus.
If you're interested in one of these positions, please send us your resume, some sample Python code that you wrote, and links to any open-source projects you've contributed to. We're looking forward to meeting you!
August 26 2010 by Tobias McNulty
DjangoCon 2010 is just around the corner, and I'm proud to announce that Caktus is sponsoring the conference again this year!
DjangoCon is the annual gathering of software developers who use the open source, Python-based Django web framework. We use the framework every day here at Caktus to create custom web applications and dynamic, content-rich web sites. Additionally, starting this year, we've put some of that knowledge to use extending and developing applications for the RapidSMS framework. For more information about why we use Django and think it's so great, check out our blog post titled Why Caktus Uses Django.
This year, the conference is being held again the week of September 6th in the beautiful city of Portland, Oregon. We've grown a little since last year at this time; it looks like 6 Caktus team members—Colin, Alex, Karen, Mark, Mike, and myself—will be attending the conference. We're positively thrilled to be going again this year and we hope to see you there!
August 12 2010 by Tobias McNulty
I'm delighted to welcome Karey Tracey to our growing team of web developers here at Caktus. Karen is a core developer of the Django web framework and specializes in the development and testing of applications for the web. She is also the author of Django 1.1 Testing and Debugging, published by Packt Publishing in April, 2010.
Caktus is a seasoned team of web developers that creates interactive, content-rich sites and applications with the Django web framework. We put a strong emphasis on best practices, employ an agile method, and also actively participate in the Django development community.
For more information about Caktus and our team, check out our newly updated team page!
June 07 2010 by Tobias McNulty
We're pleased to announce the release of the latest and greatest Caktus web presence yet. This edition features an enhanced services section and portfolio. Among other things, the new site demonstrates how our Django-based content management system can be used to connect related pages in customized, innovative ways.
In addition to Django web apps we've been building for years here at Caktus, we're now offering a related service in the mobile health development. Using RapidSMS, a communications framework built on Django, we build applications that add an SMS (text message) component to the standard Django stack. This allows non-standard users, such as clinic and community health workers, to interact with the system. Coupling high-tech and low-tech in this way lets us help remedy communication problems in places where Internet (and even power) are not widely available.
Check out the new site, and please let us know if you have any questions or comments!
April 22 2010 by Colin Copeland
Deployment is usually a tedious process with lots of tinkering until everything is setup just right. We deploy quite a few Django sites on a regular basis here at Caktus and still do tinkering, but we've attempted to functionalize some of the core tasks to ease the process. I've put together a basic example that outlines local and remote environment setup. This is a simplified example and just one of many ways to deploy a Django project (I learned a lot from Jacob Kaplan-Moss' django-deployment-workshop), so I encourage you to browse around the Django community to learn more.
The entire source for this example project can be found in the caktus-deployment Bitbucket repository.
Local Development Environment
The project directory is organized like so:
caktus_website/
__init__.py
apache/
staging.conf -- staging Apache conf
staging.wsgi -- staging wsgi file
blog/
bootstrap.py -- bootstrap local environment
fabfile.py -- manage remote environments with fabric
local_settings.py
manage.py
media/
requirements/
apps.txt -- pip requirements file
settings.py
settings_staging.py -- staging settings file
urls.py
To setup a local development environment, we'll create a virtual environment and run bootstrap.py, which is just a simple script that automates installing Python dependencies using pip:
if "VIRTUAL_ENV" not in os.environ:
sys.stderr.write("$VIRTUAL_ENV not found.\n\n")
parser.print_usage()
sys.exit(-1)
virtualenv = os.environ["VIRTUAL_ENV"]
file_path = os.path.dirname(__file__)
subprocess.call(["pip", "install", "-E", virtualenv, "--requirement",
os.path.join(file_path, "requirements/apps.txt")])
bootstrap.py uses requirements/apps.txt (a pip requirements file), so you can source anything off of PyPI as well as mercurial, git, and SVN repositories that include setup.py files. In this example, django's SVN is the only dependency in apps.txt:
-e svn+http://code.djangoproject.com/svn/django/branches/releases/1.1.X#egg=django
bootstrap.py must be run within virtual environment, so let's create a new virtualenv (I recommend using virtualenvwrapper) and then run bootstrap.py to install the dependencies:
copelco@montgomery:~/caktus_website$ mkvirtualenv --distribute caktus
(caktus)copelco@montgomery:~/caktus_website$ ./bootstrap.py
Now that our environment is setup (and Django is on the python path), we can run normal Django management commands:
(caktus)copelco@montgomery:~/caktus_website$ ./manage.py syncdb --settings=caktus_website.local_settings
(caktus)copelco@montgomery:~/caktus_website$ ./manage.py runserver --settings=caktus_website.local_settings
Great! That's it for our local setup, let's look into deploying the project to a staging server.
Deployment and Remote Management
To help provision the remote server environment (in this case Ubuntu 9.10), we'll use fabric. fabric allows you to streamline deployment by functionalizing common tasks in Python. I've created an example fabfile.py to help bootstrap and deploy the project:
(caktus)copelco@montgomery:~/caktus_website$ fab --list
Available commands:
apache_reload reload Apache on remote host
apache_restart restart Apache on remote host
bootstrap initialize remote host environment (virtualenv, dep...
configtest test Apache configuration
create_virtualenv setup virtualenv on remote host
deploy rsync code to remote host
production use production environment on remote host
staging use staging environment on remote host
symlink_django create symbolic link so Apache can serve django adm...
touch touch wsgi file to trigger reload
update_apache_conf upload apache configuration to remote host
update_requirements update external dependencies on remote host
The fabfile splits the deployment process into discrete steps of 1) virtual environment creation, 2) code transfer, and 3) updating the Python dependencies. The bootstrap command wraps everything together, including initial directory creation, so you can setup the server quickly:
def bootstrap():
""" initialize remote host environment (virtualenv, deploy, update) """
require('root', provided_by=('staging', 'production'))
run('mkdir -p %(root)s' % env)
run('mkdir -p %s' % os.path.join(env.home, 'www', 'log'))
create_virtualenv()
deploy()
update_requirements()
def create_virtualenv():
""" setup virtualenv on remote host """
require('virtualenv_root', provided_by=('staging', 'production'))
args = '--clear --distribute'
run('virtualenv %s %s' % (args, env.virtualenv_root))
def deploy():
""" rsync code to remote host """
require('root', provided_by=('staging', 'production'))
if env.environment == 'production':
if not console.confirm('Are you sure you want to deploy production?',
default=False):
utils.abort('Production deployment aborted.')
extra_opts = '--omit-dir-times'
rsync_project(
env.root,
exclude=RSYNC_EXCLUDE,
delete=True,
extra_opts=extra_opts,
)
touch()
def update_requirements():
""" update external dependencies on remote host """
require('code_root', provided_by=('staging', 'production'))
requirements = os.path.join(env.code_root, 'requirements')
with cd(requirements):
cmd = ['pip install']
cmd += ['-E %(virtualenv_root)s' % env]
cmd += ['--requirement %s' % os.path.join(requirements, 'apps.txt')]
run(' '.join(cmd))
To bootstrap the staging environment, run:
(caktus)copelco@montgomery:~/caktus_website$ fab staging bootstrap
This will run a few commands over SSH and rsync the project directory to a specific location on the staging server. Using rsync is just one of many ways to transfer code to the server, such as pulling code from a remote repository. The "deploy" fabfile can be modified to perform almost any transfer task. Once the bootstrap process is complete, the directory structure will look like so:
home/
caktus/
www/
staging/
env/ -- virtual environment
bin/
include/
lib/ -- contains site-packages
source/ -- contains django src
caktus_website/
...
apache/
manage.py
requirements/
...
Now SSH to the server and run syncdb within the newly created virtual environment:
caktus@pike:~/www/staging/caktus_website$ source ../env/bin/activate
(env)caktus@pike:~/www/staging/caktus_website$ ./manage.py syncdb --settings=caktus_website.settings_staging
The staging setting's file is setup to use sqlite3 to simplify this deployment example. In practice we use PostgreSQL in our production environments, but database setup is for another blog post! To get Apache configured using mod_wsgi, we'll point the apache configuration to the staging.wsgi file using the WSGIScriptAlias directive. Here's an example Apache configuration to get a barebones Django environment up and running:
<VirtualHost:*80>
WSGIScriptReloading On
WSGIReloadMechanism Process
WSGIDaemonProcess caktus_website-staging
WSGIProcessGroup caktus_website-staging
WSGIApplicationGroup caktus_website-staging
WSGIPassAuthorization On
WSGIScriptAlias / /home/caktus/www/staging/caktus_website/apache/staging.wsgi/
<Location "/">
Order Allow,Deny
Allow from all
</Location>
<Location "/media">
SetHandler None
</Location>
Alias /media /home/caktus/www/staging/caktus_website/media
<Location "/admin-media">
SetHandler None
</Location>
Alias /admin-media /home/caktus/www/staging/caktus_website/media/admin
ErrorLog /home/caktus/www/log/error.log
LogLevel info
CustomLog /home/caktus/www/log/access.log combined
</VirtualHost:*80>
We'll use Apache to serve static media (both local and admin media) and direct everything else to the Django instance through mod_wsgi. In order for the wsgi instance to be aware of our environment and project directory, we need to add the virtual environment's site-packages directory, the project directory to the python path, and tell Django which settings file to use by setting the DJANGO_SETTINGS_MODULE environment variable:
import os
import sys
import site
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
site_packages = os.path.join(PROJECT_ROOT, 'env/lib/python2.6/site-packages')
site.addsitedir(os.path.abspath(site_packages))
sys.path.insert(0, PROJECT_ROOT)
os.environ['DJANGO_SETTINGS_MODULE'] = 'caktus_website.settings_staging'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
Now just upload the staging apache configuration and reload apache:
(caktus)copelco@montgomery:~/caktus_website$ fab staging update_apache_conf
That's it! The site should be up and running on your server's public IP. If you run into any trouble (like a 500 Internal Server Error), just tail the Apache error.log, it'll usually point you in the right direction.
March 16 2010 by Tobias McNulty
Django is a tool we use every day to build fantastic web apps here at Caktus, and a development sprint is a concerted, focused period of time in which developers meet in the same space to get things done on a project.
We're proud to annouce that Caktus is hosting another local Django development sprint in the Triangle (Raleigh, Durham, and Chapel Hill/Carrboro) area of North Carolina. The sprint will be held the weekend of March 20th and 21st in Carrboro Creative Coworking, and the purpose of this sprint will be to help push out bug fixes in preparation for the upcoming Django 1.2 release.
If you're interested in attending, no previous experience contributing to Django is necessary and the sprint will be a great opportunity to start. Work on other open source Django-based projects is welcome too. For more information, check out the corresponding wiki page.
We'll be there to open the doors at 9am both days. Courtesy of our sponsors there will be free drinks, snacks, and lunch to go around. Hope to see you there!
March 11 2010 by Tobias McNulty
Like just about everyone else, we've written our own suite of tools to help with building complex content management systems in Django here at Caktus. We reviewed a number of the existing CMSes out there, but in almost every case the navigation and page structure were so tightly coupled the system broke down when it came time to add additional, non-CMS pages.
We wrote a few little apps, django-pagelets, django-treenav, and django-crumbs, each of which manages different pieces of content (little snippets of content, full CMS pages, navigation, and breadcrumbs). All of the apps are available for free under an open source license on Google Code.
Decoupling was a great move for us, and the ability to plug and play any single part of the system is a huge benefit. Sometimes, however, the completely decoupled architecture was a bit of a pain: If we didn't provide a link from the pagelets app to the treenav app, how would it be possible to edit a page's corresponding navigation item on its change form in the Django admin interface?
Enter Generic Relations. Using Django's content types framework, it's possible to create admin inlines for generic relations with just a few simple lines of code.
In this case, I'll show how we allowed users to edit a page's corresponding navigation item in django-pagelets without requiring everyone (i.e., those who don't need it) to install django-treenav. First, define the generic inline in the admin.py file of the app that contains the model you want to link to:
from django.contrib.contenttypes import generic
class GenericMenuItemInline(generic.GenericStackedInline):
"""
Add this inline to your admin class to support editing related menu items
from that model's admin page.
"""
max_num = 1
model = treenav.MenuItem
Then, inside the Admin class for the related model in question, dynamically import and add GenericMenuItemInline to the admin's list of inlines based on whether or not it's in the project's INSTALLED_APPS:
from django.conf import settings
class PageAdmin(admin.ModelAdmin):
# ...
inlines = [MyOtherInline]
if 'treenav' in settings.INSTALLED_APPS:
from treenav.admin import GenericMenuItemInline
inlines.insert(0, GenericMenuItemInline)
For more information, see the corresponding pagelets admin.py and treenav admin.py. Thanks for reading and don't hesitate to post comments if you have any questions!
March 08 2010 by Colin Copeland
We're always looking for new tools to make our development environment more robust here at Caktus. We write a lot of tests to ensure proper functionality as new features land and bug fixes are added to our projects. The next step is to integrate with a continuous integration system to automate the process and regularly check that status of the build.
After attending Dr. C. Titus Brown's "Why not run all your tests all the time? A study of continuous integration systems." talk at Pycon and seeing Django's Hudson setup, I figured I'd take a look at Hudson CI.
Installing Hudson and basic setup
Hudson is very easy to setup. I started with a fresh Ubuntu 9.10 install on the smallest Rackspace cloud instance and had it running after a few commands. I followed the Debian setup instructions, which basically consists of:
$ wget -O - http://hudson-ci.org/debian/hudson-ci.org.key | sudo apt-key add -
$ echo "deb http://hudson-ci.org/debian binary/" >> /etc/apt/sources.list
$ apt-get update
$ aptitude install hudson
$ apt-get upgrade
That's it! It's already up and running on port 8080 using it's own web server. Go ahead and pull it up in your browser.
As a test, let's setup django-crm (a Caktus open-source community project) as our first Hudson job. Click "New Job", type in a job name, click "Build a free-style software project", and hit OK. django-crm contains a sample project that we'll use to run the test suite. On the job configuration page, check Subversion in the Source Code Management section and type in the Repository URL:

Click Save, run the job by clicking "Build Now", and check out the Console Output:
Started by user anonymous
Checking out a fresh workspace because /var/lib/hudson/jobs/django-crm/workspace/sample_project doesn't exist
Checking out http://django-crm.googlecode.com/svn/trunk/sample_project
A manage.py
A site_media
A site_media/css
A site_media/css/jquery.autocomplete.css
A site_media/css/django-contactinfo.css
A site_media/js
A site_media/js/jquery-ui-1.7.2.custom.min.js
A site_media/js/jquery-1.3.2.min.js
A site_media/js/django-crm.js
A site_media/js/jquery.autocomplete.min.js
...
Finished: SUCCESS
Cool, now let's run some tests. Too keep things simple, let's grab Django and a few dependencies using aptitude:
$ wget http://www.djangoproject.com/download/1.1.1/tarball/
$ tar xzvf Django-1.1.1.tar.gz
$ cd Django-1.1.1
$ sudo python setup.py install
$ aptitude install python-dev python-imaging python-setuptools python-pip
To run the tests, add an "Execute shell" build step in the Build section with this command:
#!/bin/bash -ex
cd sample_project
python manage.py test crm
Run the job again and look for the test results in the console output:
[workspace] $ /bin/sh -xe /tmp/hudson6670261053226891793.sh
+ cd sample_project
+ python manage.py test crm
...
Finished: SUCCESS
XML Test output
To integrate Hudson with the Django test suite, I used unittest-xml-reporting. Just "pip install unittest-xml-reporting" and add the following lines to your settings file:
TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.run_tests'
TEST_OUTPUT_VERBOSE = True
TEST_OUTPUT_DESCRIPTIONS = True
TEST_OUTPUT_DIR = 'xmlrunner'
Then check "Publish JUnit test result report" in the Post-build Actions section and add the path to the test XML output "sample_project/xmlrunner/*.xml":

Run the job and you should see a new "Test Result" link in the navigation. Now you can view the test results right in your browser window.
Coverage
To add coverage reports, I used Ned Batchelder's coverage.py (pip install coverage). Navigate to Hudson's plugin manager (Hudson -> Manage Hudson -> Manage Plugins), install the Cobertura Plugin, and restart Hudson when prompted. Then modify your shell script like so:
#!/bin/bash -ex
cd sample_project
coverage run manage.py test crm
coverage xml --omit=/usr/
This will generate an XML coverage report in the working directory, so we just need to tell Hudson where to look for it. Check "Publish Cobertura Coverage Report" in the Post-build Actions section and enter the path to the report:

Run the build again and you should have access to a new "Coverage Report" link.
More to come...
This was just a simple example of getting Hudson setup with a Django project and I know a lot more can be done with Hudson (check out the large number of available plugins). The top items on my todo list are: see Hudson setup environments with virtualenv and pip, integrate more closely with the test suite (possibly using nose), check for PEP compliance, and setup build failure notifications. I hope to write more as I continue to setup our Hudson environment!
References
A few useful Hudson/Python/Django links I discovered while running through this setup:
February 17 2010 by Tobias McNulty
Python and Django are tools we use on a daily basis to build fantastic web apps here at Caktus. I'm pleased to announce that Caktus is sending five developers--Colin, Alex, Mike, Mark, and myself--to PyCon 2010! PyCon is an annual gathering for users and developers of the open source Python programming language. This year the US conference is being held in Atlanta, GA. We'll be driving down tomorrow (Thursday) from Chapel Hill, NC and staying for the conference weekend plus one day of the sprints.
Hope to see you there!
December 06 2009 by Tobias McNulty
Django is a tool we use every day to build rock-solid web apps here at Caktus, and a development sprint is a concerted, focused period of time in which developers meet in the same space to get things done on a project.
We're proud to annouce that Caktus is hosting a local Django development sprint in the Triangle (Raleigh, Durham, and Chapel Hill/Carrboro) area of North Carolina. The sprint will be held the weekend of December 12th and 13th in Carrboro Creative Coworking, and the purpose of this sprint will be to help finish features and push out bug fixes in preparation for the upcoming Django 1.2 release.
If you're interested in attending, no previous experience contributing to Django is necessary and the sprint will be a great opportunity to start. Work on other open source Django-based projects is welcome too. For more information, check out the corresponding wiki page and don't forget to register for the event.
We'll be there to open the doors at 9am both days. Courtesy of our sponsors there will be free drinks, snacks, and lunch to go around. Hope to see you there!