<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Caktus Blog &#187; django</title>
	<atom:link href="http://www.caktusgroup.com/blog/feed/?tag=django" rel="self" type="application/rss+xml" />
	<link>http://www.caktusgroup.com/blog</link>
	<description>Blog &#124; Django Web Development &#124; Raleigh Durham Chapel Hill &#124; Caktus Consulting Group</description>
	<pubDate>Fri, 03 Sep 2010 16:13:21 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>Caktus Consulting Group Seeks Two Python/Django Web Developers</title>
		<link>http://www.caktusgroup.com/blog/2010/09/03/caktus-consulting-group-seeks-two-python-django-web-developers/</link>
		<comments>http://www.caktusgroup.com/blog/2010/09/03/caktus-consulting-group-seeks-two-python-django-web-developers/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 16:13:03 +0000</pubDate>
		<dc:creator>tobias</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[djangocon]]></category>

		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=485</guid>
		<description><![CDATA[I&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m delighted to announce that <a href="http://www.caktusgroup.com/">Caktus</a> 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.</p>
<p>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 <a href="http://www.carrborocoworking.com/">Carrboro Creative Coworking</a>).  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 <a href="/about/">meet the team</a> and learn more about <a href="/services/">what we do</a>.</p>
<p>We&#8217;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.</p>
<p>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.</p>
<p>If you&#8217;re interested in one of these positions, please <a href="mailto:jobs+caktus@caktusgroup.com?subject=Developer for Hire">send us</a> your resume, some sample Python code that you wrote, and links to any open-source projects you&#8217;ve contributed to.  We&#8217;re looking forward to meeting you!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2010/09/03/caktus-consulting-group-seeks-two-python-django-web-developers/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Caktus Consulting Group Sponsors DjangoCon 2010</title>
		<link>http://www.caktusgroup.com/blog/2010/08/26/caktus-consulting-group-sponsors-djangocon-2010/</link>
		<comments>http://www.caktusgroup.com/blog/2010/08/26/caktus-consulting-group-sponsors-djangocon-2010/#comments</comments>
		<pubDate>Thu, 26 Aug 2010 18:50:45 +0000</pubDate>
		<dc:creator>tobias</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[djangocon]]></category>

		<category><![CDATA[open source]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[rapidsms]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=468</guid>
		<description><![CDATA[DjangoCon 2010 is just around the corner, and I&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://djangocon.us">DjangoCon 2010</a> is just around the corner, and I&#8217;m proud to announce that Caktus is sponsoring the conference again this year!</p>
<p>DjangoCon is the annual gathering of software developers who use the open source, Python-based <a href="http://www.djangoproject.com/">Django web framework</a>.  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&#8217;ve put some of that knowledge to use extending and developing applications for the <a href="http://www.rapidsms.org">RapidSMS</a> framework.  For more information about why we use Django and think it&#8217;s so great, check out our blog post titled <a href="http://www.caktusgroup.com/blog/2009/01/13/why-caktus-uses-django/">Why Caktus Uses Django</a>.</p>
<p>This year, the conference is being held again the week of September 6th in the beautiful city of Portland, Oregon. We&#8217;ve grown a little since last year at this time; it looks like 6 Caktus team members&mdash;Colin, Alex, Karen, Mark, Mike, and myself&mdash;will be attending the conference. We&#8217;re positively thrilled to be going again this year and we hope to see you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2010/08/26/caktus-consulting-group-sponsors-djangocon-2010/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Caktus Consulting Group Welcomes Lead Developer Karen Tracey</title>
		<link>http://www.caktusgroup.com/blog/2010/08/12/caktus-consulting-group-welcomes-lead-developer-karen-tracey/</link>
		<comments>http://www.caktusgroup.com/blog/2010/08/12/caktus-consulting-group-welcomes-lead-developer-karen-tracey/#comments</comments>
		<pubDate>Thu, 12 Aug 2010 20:10:43 +0000</pubDate>
		<dc:creator>tobias</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=459</guid>
		<description><![CDATA[I&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;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 <a href="https://www.packtpub.com/django-1-1-testing-and-debugging/book"><em>Django 1.1 Testing and Debugging</em></a>, published by Packt Publishing in April, 2010.</p>
<p>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.</p>
<p>For more information about Caktus and our team, check out our newly updated <a href="/about/">team page</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2010/08/12/caktus-consulting-group-welcomes-lead-developer-karen-tracey/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Expanded services, portfolio, and more in the new Caktus web site</title>
		<link>http://www.caktusgroup.com/blog/2010/06/07/expanded-services-portfolio-and-more-in-the-new-caktus-web-site/</link>
		<comments>http://www.caktusgroup.com/blog/2010/06/07/expanded-services-portfolio-and-more-in-the-new-caktus-web-site/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 21:46:20 +0000</pubDate>
		<dc:creator>tobias</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[content management]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[mobile health]]></category>

		<category><![CDATA[rapidsms]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=452</guid>
		<description><![CDATA[We&#8217;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&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re pleased to announce the release of the latest and greatest Caktus web presence yet.  This edition features an enhanced <a href="/services/">services section</a> and <a href="/portfolio/">portfolio</a>. Among other things, the new site demonstrates how our <a href="/content-management/">Django-based content management system</a> can be used to connect related pages in customized, innovative ways.</p>
<p>In addition to Django web apps we&#8217;ve been building for years here at Caktus, we&#8217;re now offering a related service in the <a href="/mobile-health/">mobile health development</a>.  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.</p>
<p>Check out the new site, and please let us know if you have any questions or comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2010/06/07/expanded-services-portfolio-and-more-in-the-new-caktus-web-site/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Basic Django deployment with virtualenv, fabric, pip and rsync</title>
		<link>http://www.caktusgroup.com/blog/2010/04/22/basic-django-deployment-with-virtualenv-fabric-pip-and-rsync/</link>
		<comments>http://www.caktusgroup.com/blog/2010/04/22/basic-django-deployment-with-virtualenv-fabric-pip-and-rsync/#comments</comments>
		<pubDate>Fri, 23 Apr 2010 01:46:37 +0000</pubDate>
		<dc:creator>Colin Copeland</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[postgresql]]></category>

		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=443</guid>
		<description><![CDATA[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&#8217;ve attempted to functionalize some of the core tasks to ease the process. I&#8217;ve put together a basic example that [...]]]></description>
			<content:encoded><![CDATA[<p>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&#8217;ve attempted to functionalize some of the core tasks to ease the process. I&#8217;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&#8217; <a href="http://github.com/jacobian/django-deployment-workshop/">django-deployment-workshop</a>), so I encourage you to browse around the Django community to learn more.</p>
<p>The entire source for this example project can be found in the <a href="http://www.bitbucket.org/copelco/caktus-deployment/src/tip/example-django-project/">caktus-deployment Bitbucket repository</a>.</p>
<h2>Local Development Environment</h2>
<p>The project directory is organized like so:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">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</pre></div></div>

<p>To setup a local development environment, we&#8217;ll create a virtual environment and run bootstrap.py, which is just a simple script that automates installing Python dependencies using <a href="http://pip.openplans.org/">pip</a>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">&quot;VIRTUAL_ENV&quot;</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span>:
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;$VIRTUAL_ENV not found.<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">print_usage</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
virtualenv = <span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;VIRTUAL_ENV&quot;</span><span style="color: black;">&#93;</span>
file_path = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span>
<span style="color: #dc143c;">subprocess</span>.<span style="color: black;">call</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;pip&quot;</span>, <span style="color: #483d8b;">&quot;install&quot;</span>, <span style="color: #483d8b;">&quot;-E&quot;</span>, virtualenv, <span style="color: #483d8b;">&quot;--requirement&quot;</span>,
                 <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>file_path, <span style="color: #483d8b;">&quot;requirements/apps.txt&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>bootstrap.py uses requirements/apps.txt (a <a href="http://pip.openplans.org/requirement-format.html">pip requirements file</a>), so you can source anything off of <a href="http://pypi.python.org/">PyPI</a> as well as mercurial, git, and SVN repositories that include setup.py files. In this example, django&#8217;s SVN is the only dependency in apps.txt:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">-e svn+http://code.djangoproject.com/svn/django/branches/releases/1.1.X#egg=django</pre></div></div>

<p>bootstrap.py must be run within virtual environment, so let&#8217;s create a new virtualenv (I recommend using <a href="http://www.doughellmann.com/projects/virtualenvwrapper/">virtualenvwrapper</a>) and then run bootstrap.py to install the dependencies:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">copelco<span style="color: #000000; font-weight: bold;">@</span>montgomery:~<span style="color: #000000; font-weight: bold;">/</span>caktus_website$ mkvirtualenv <span style="color: #660033;">--distribute</span> caktus
<span style="color: #7a0874; font-weight: bold;">&#40;</span>caktus<span style="color: #7a0874; font-weight: bold;">&#41;</span>copelco<span style="color: #000000; font-weight: bold;">@</span>montgomery:~<span style="color: #000000; font-weight: bold;">/</span>caktus_website$ .<span style="color: #000000; font-weight: bold;">/</span>bootstrap.py</pre></div></div>

<p>Now that our environment is setup (and Django is on the python path), we can run normal Django management commands:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#40;</span>caktus<span style="color: #7a0874; font-weight: bold;">&#41;</span>copelco<span style="color: #000000; font-weight: bold;">@</span>montgomery:~<span style="color: #000000; font-weight: bold;">/</span>caktus_website$ .<span style="color: #000000; font-weight: bold;">/</span>manage.py syncdb --<span style="color: #007800;">settings</span>=caktus_website.local_settings
<span style="color: #7a0874; font-weight: bold;">&#40;</span>caktus<span style="color: #7a0874; font-weight: bold;">&#41;</span>copelco<span style="color: #000000; font-weight: bold;">@</span>montgomery:~<span style="color: #000000; font-weight: bold;">/</span>caktus_website$ .<span style="color: #000000; font-weight: bold;">/</span>manage.py runserver --<span style="color: #007800;">settings</span>=caktus_website.local_settings</pre></div></div>

<p>Great! That&#8217;s it for our local setup, let&#8217;s look into deploying the project to a staging server.</p>
<h2>Deployment and Remote Management</h2>
<p>To help provision the remote server environment (in this case Ubuntu 9.10), we&#8217;ll use <a href="http://docs.fabfile.org/0.9.0/">fabric</a>. fabric allows you to streamline deployment by functionalizing common tasks in Python. I&#8217;ve created an example fabfile.py to help bootstrap and deploy the project:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#40;</span>caktus<span style="color: #7a0874; font-weight: bold;">&#41;</span>copelco<span style="color: #000000; font-weight: bold;">@</span>montgomery:~<span style="color: #000000; font-weight: bold;">/</span>caktus_website$ fab <span style="color: #660033;">--list</span>
Available commands:
&nbsp;
    apache_reload        reload Apache on remote host
    apache_restart       restart Apache on remote host
    bootstrap            initialize remote host environment <span style="color: #7a0874; font-weight: bold;">&#40;</span>virtualenv, dep...
    configtest           <span style="color: #7a0874; font-weight: bold;">test</span> 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 <span style="color: #c20cb9; font-weight: bold;">link</span> so Apache can serve django adm...
    <span style="color: #c20cb9; font-weight: bold;">touch</span>                <span style="color: #c20cb9; font-weight: bold;">touch</span> wsgi <span style="color: #c20cb9; font-weight: bold;">file</span> to trigger reload
    update_apache_conf   upload apache configuration to remote host
    update_requirements  update external dependencies on remote host</pre></div></div>

<p>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:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> bootstrap<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; initialize remote host environment (virtualenv, deploy, update) &quot;&quot;&quot;</span>
    require<span style="color: black;">&#40;</span><span style="color: #483d8b;">'root'</span>, provided_by=<span style="color: black;">&#40;</span><span style="color: #483d8b;">'staging'</span>, <span style="color: #483d8b;">'production'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir -p %(root)s'</span> <span style="color: #66cc66;">%</span> env<span style="color: black;">&#41;</span>
    run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir -p %s'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>env.<span style="color: black;">home</span>, <span style="color: #483d8b;">'www'</span>, <span style="color: #483d8b;">'log'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    create_virtualenv<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    deploy<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    update_requirements<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> create_virtualenv<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; setup virtualenv on remote host &quot;&quot;&quot;</span>
    require<span style="color: black;">&#40;</span><span style="color: #483d8b;">'virtualenv_root'</span>, provided_by=<span style="color: black;">&#40;</span><span style="color: #483d8b;">'staging'</span>, <span style="color: #483d8b;">'production'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    args = <span style="color: #483d8b;">'--clear --distribute'</span>
    run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'virtualenv %s %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>args, env.<span style="color: black;">virtualenv_root</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> deploy<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; rsync code to remote host &quot;&quot;&quot;</span>
    require<span style="color: black;">&#40;</span><span style="color: #483d8b;">'root'</span>, provided_by=<span style="color: black;">&#40;</span><span style="color: #483d8b;">'staging'</span>, <span style="color: #483d8b;">'production'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> env.<span style="color: black;">environment</span> == <span style="color: #483d8b;">'production'</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> console.<span style="color: black;">confirm</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Are you sure you want to deploy production?'</span>,
                               default=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
            utils.<span style="color: black;">abort</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Production deployment aborted.'</span><span style="color: black;">&#41;</span>
    extra_opts = <span style="color: #483d8b;">'--omit-dir-times'</span>
    rsync_project<span style="color: black;">&#40;</span>
        env.<span style="color: black;">root</span>,
        exclude=RSYNC_EXCLUDE,
        delete=<span style="color: #008000;">True</span>,
        extra_opts=extra_opts,
    <span style="color: black;">&#41;</span>
    touch<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> update_requirements<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; update external dependencies on remote host &quot;&quot;&quot;</span>
    require<span style="color: black;">&#40;</span><span style="color: #483d8b;">'code_root'</span>, provided_by=<span style="color: black;">&#40;</span><span style="color: #483d8b;">'staging'</span>, <span style="color: #483d8b;">'production'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    requirements = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>env.<span style="color: black;">code_root</span>, <span style="color: #483d8b;">'requirements'</span><span style="color: black;">&#41;</span>
    with <span style="color: #dc143c;">cd</span><span style="color: black;">&#40;</span>requirements<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">cmd</span> = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'pip install'</span><span style="color: black;">&#93;</span>
        <span style="color: #dc143c;">cmd</span> += <span style="color: black;">&#91;</span><span style="color: #483d8b;">'-E %(virtualenv_root)s'</span> <span style="color: #66cc66;">%</span> env<span style="color: black;">&#93;</span>
        <span style="color: #dc143c;">cmd</span> += <span style="color: black;">&#91;</span><span style="color: #483d8b;">'--requirement %s'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>requirements, <span style="color: #483d8b;">'apps.txt'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
        run<span style="color: black;">&#40;</span><span style="color: #483d8b;">' '</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmd</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>To bootstrap the staging environment, run:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#40;</span>caktus<span style="color: #7a0874; font-weight: bold;">&#41;</span>copelco<span style="color: #000000; font-weight: bold;">@</span>montgomery:~<span style="color: #000000; font-weight: bold;">/</span>caktus_website$ fab staging bootstrap</pre></div></div>

<p>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 &#8220;deploy&#8221; fabfile can be modified to perform almost any transfer task. Once the bootstrap process is complete, the directory structure will look like so:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">home/
    caktus/
        www/
            staging/
                env/               -- virtual environment
                    bin/
                    include/
                    lib/           -- contains site-packages
                    source/        -- contains django src
                caktus_website/
                    ...
                    apache/
                    manage.py
                    requirements/
                    ...</pre></div></div>

<p>Now SSH to the server and run syncdb within the newly created virtual environment:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">caktus<span style="color: #000000; font-weight: bold;">@</span>pike:~<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>staging<span style="color: #000000; font-weight: bold;">/</span>caktus_website$ <span style="color: #7a0874; font-weight: bold;">source</span> ..<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">env</span><span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>activate
<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">env</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>caktus<span style="color: #000000; font-weight: bold;">@</span>pike:~<span style="color: #000000; font-weight: bold;">/</span>www<span style="color: #000000; font-weight: bold;">/</span>staging<span style="color: #000000; font-weight: bold;">/</span>caktus_website$ .<span style="color: #000000; font-weight: bold;">/</span>manage.py syncdb --<span style="color: #007800;">settings</span>=caktus_website.settings_staging</pre></div></div>

<p>The staging setting&#8217;s file is setup to use sqlite3 to simplify this deployment example. In practice we use <a href="http://www.postgresql.org/">PostgreSQL</a> in our production environments, but database setup is for another blog post! To get Apache configured using mod_wsgi, we&#8217;ll point the apache configuration to the staging.wsgi file using the WSGIScriptAlias directive. Here&#8217;s an example Apache configuration to get a barebones Django environment up and running:</p>

<div class="wp_syntax"><div class="code"><pre class="apache apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">VirtualHost</span> *:<span style="color: #ff0000;">80</span>&gt;
    WSGIScriptReloading <span style="color: #0000ff;">On</span>
    WSGIReloadMechanism Process
    WSGIDaemonProcess caktus_website-staging
    WSGIProcessGroup caktus_website-staging
    WSGIApplicationGroup caktus_website-staging
    WSGIPassAuthorization <span style="color: #0000ff;">On</span>
&nbsp;
    WSGIScriptAlias / /home/caktus/www/staging/caktus_website/apache/staging.wsgi/
&nbsp;
    &lt;<span style="color: #000000; font-weight:bold;">Location</span> <span style="color: #7f007f;">&quot;/&quot;</span>&gt;
        <span style="color: #00007f;">Order</span> <span style="color: #00007f;">Allow</span>,<span style="color: #00007f;">Deny</span>
        <span style="color: #00007f;">Allow</span> <span style="color: #00007f;">from</span> <span style="color: #00007f;">all</span>
    &lt;/<span style="color: #000000; font-weight:bold;">Location</span>&gt;
&nbsp;
    &lt;<span style="color: #000000; font-weight:bold;">Location</span> <span style="color: #7f007f;">&quot;/media&quot;</span>&gt;
        <span style="color: #00007f;">SetHandler</span> <span style="color: #0000ff;">None</span>
    &lt;/<span style="color: #000000; font-weight:bold;">Location</span>&gt;
&nbsp;
    <span style="color: #00007f;">Alias</span> /media /home/caktus/www/staging/caktus_website/media
&nbsp;
    &lt;<span style="color: #000000; font-weight:bold;">Location</span> <span style="color: #7f007f;">&quot;/admin-media&quot;</span>&gt;
        <span style="color: #00007f;">SetHandler</span> <span style="color: #0000ff;">None</span>
    &lt;/<span style="color: #000000; font-weight:bold;">Location</span>&gt;
&nbsp;
    <span style="color: #00007f;">Alias</span> /admin-media /home/caktus/www/staging/caktus_website/media/admin
&nbsp;
    <span style="color: #00007f;">ErrorLog</span> /home/caktus/www/log/error.log
    <span style="color: #00007f;">LogLevel</span> info
    <span style="color: #00007f;">CustomLog</span> /home/caktus/www/log/access.log combined
&lt;/<span style="color: #000000; font-weight:bold;">VirtualHost</span>&gt;</pre></div></div>

<p>We&#8217;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&#8217;s site-packages directory, the project directory to the python path, and tell Django which settings file to use by setting the <a href="http://docs.djangoproject.com/en/dev/topics/settings/#designating-the-settings">DJANGO_SETTINGS_MODULE environment variable</a>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">site</span>
&nbsp;
PROJECT_ROOT = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
site_packages = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>PROJECT_ROOT, <span style="color: #483d8b;">'env/lib/python2.6/site-packages'</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">site</span>.<span style="color: black;">addsitedir</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">abspath</span><span style="color: black;">&#40;</span>site_packages<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>.<span style="color: black;">insert</span><span style="color: black;">&#40;</span>0, PROJECT_ROOT<span style="color: black;">&#41;</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'caktus_website.settings_staging'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>
application = django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>.<span style="color: black;">WSGIHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Now just upload the staging apache configuration and reload apache:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#40;</span>caktus<span style="color: #7a0874; font-weight: bold;">&#41;</span>copelco<span style="color: #000000; font-weight: bold;">@</span>montgomery:~<span style="color: #000000; font-weight: bold;">/</span>caktus_website$ fab staging update_apache_conf</pre></div></div>

<p>That&#8217;s it! The site should be up and running on your server&#8217;s public IP. If you run into any trouble (like a 500 Internal Server Error), just tail the Apache error.log, it&#8217;ll usually point you in the right direction.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2010/04/22/basic-django-deployment-with-virtualenv-fabric-pip-and-rsync/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Caktus Consulting Group hosts 2nd Django sprint in NC Triangle area</title>
		<link>http://www.caktusgroup.com/blog/2010/03/16/caktus-consulting-group-hosts-2nd-django-sprint-in-nc-triangle-area/</link>
		<comments>http://www.caktusgroup.com/blog/2010/03/16/caktus-consulting-group-hosts-2nd-django-sprint-in-nc-triangle-area/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 17:36:31 +0000</pubDate>
		<dc:creator>tobias</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[sprint]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=431</guid>
		<description><![CDATA[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&#8217;re proud to annouce that Caktus is hosting another local Django development sprint in [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.djangoproject.com/">Django</a> is a tool we use every day to build <a href="http://www.caktusgroup.com/services/">fantastic web apps</a> 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.</p>
<p>We&#8217;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 <a href="http://carrborocoworking.com/">Carrboro Creative Coworking</a>, and the purpose of this sprint will be to help push out bug fixes in preparation for the upcoming Django 1.2 release.</p>
<p>If you&#8217;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 <a href="http://code.djangoproject.com/wiki/Sprint201003TriangleNC">corresponding wiki page</a>.</p>
<p>We&#8217;ll be there to open the doors at 9am both days.  Courtesy of our <a href="http://code.djangoproject.com/wiki/Sprint201003TriangleNC#Sponsors">sponsors</a> there will be free drinks, snacks, and lunch to go around.  Hope to see you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2010/03/16/caktus-consulting-group-hosts-2nd-django-sprint-in-nc-triangle-area/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Decoupled Django Apps and the Beauty of Generic Relations</title>
		<link>http://www.caktusgroup.com/blog/2010/03/11/decoupled-django-apps-and-the-beauty-of-generic-relations/</link>
		<comments>http://www.caktusgroup.com/blog/2010/03/11/decoupled-django-apps-and-the-beauty-of-generic-relations/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 21:18:02 +0000</pubDate>
		<dc:creator>tobias</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[admin]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[generic relations]]></category>

		<category><![CDATA[open source]]></category>

		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=405</guid>
		<description><![CDATA[Like just about everyone else, we&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p>Like just about everyone else, we&#8217;ve written our own suite of tools to help with building complex content management systems in Django here at <a href="http://www.caktusgroup.com/services">Caktus</a>.  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.</p>
<p>We wrote a few little apps, <a href="http://code.google.com/p/django-pagelets/">django-pagelets</a>, <a href="http://code.google.com/p/django-treenav/">django-treenav</a>, and <a href="http://code.google.com/p/django-crumbs/">django-crumbs</a>, 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.</p>
<p>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&#8217;t provide a link from the pagelets app to the treenav app, how would it be possible to edit a page&#8217;s corresponding navigation item on its change form in the Django admin interface?</p>
<p>Enter <a href="http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1">Generic Relations</a>.  Using Django&#8217;s content types framework, it&#8217;s possible to create <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/#using-generic-relations-as-an-inline">admin inlines for generic relations</a> with just a few simple lines of code.</p>
<p>In this case, I&#8217;ll show how we allowed users to edit a page&#8217;s corresponding navigation item in django-pagelets without requiring everyone (i.e., those who don&#8217;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:</p>

<div class="wp_syntax"><div class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">contenttypes</span> <span style="color: #ff7700;font-weight:bold;">import</span> generic
<span style="color: #ff7700;font-weight:bold;">class</span> GenericMenuItemInline<span style="color: black;">&#40;</span>generic.<span style="color: black;">GenericStackedInline</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Add this inline to your admin class to support editing related menu items
    from that model's admin page.
    &quot;&quot;&quot;</span>
    max_num = <span style="color: #ff4500;">1</span>
    model = treenav.<span style="color: black;">MenuItem</span></pre></div></div>

<p>Then, inside the Admin class for the related model in question, dynamically import and add  GenericMenuItemInline to the admin&#8217;s list of inlines based on whether or not it&#8217;s in the project&#8217;s INSTALLED_APPS:</p>

<div class="wp_syntax"><div class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">class</span> PageAdmin<span style="color: black;">&#40;</span>admin.<span style="color: black;">ModelAdmin</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># ...</span>
    inlines = <span style="color: black;">&#91;</span>MyOtherInline<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">'treenav'</span> <span style="color: #ff7700;font-weight:bold;">in</span> settings.<span style="color: black;">INSTALLED_APPS</span>:
        <span style="color: #ff7700;font-weight:bold;">from</span> treenav.<span style="color: black;">admin</span> <span style="color: #ff7700;font-weight:bold;">import</span> GenericMenuItemInline
        inlines.<span style="color: black;">insert</span><span style="color: black;">&#40;</span>0, GenericMenuItemInline<span style="color: black;">&#41;</span></pre></div></div>

<p>For more information, see the corresponding <a href="http://code.google.com/p/django-pagelets/source/browse/trunk/pagelets/admin.py">pagelets admin.py</a> and <a href="http://code.google.com/p/django-treenav/source/browse/trunk/treenav/admin.py">treenav admin.py</a>.  Thanks for reading and don&#8217;t hesitate to post comments if you have any questions!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2010/03/11/decoupled-django-apps-and-the-beauty-of-generic-relations/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Continuous Integration with Django and Hudson CI (Day 1)</title>
		<link>http://www.caktusgroup.com/blog/2010/03/08/django-and-hudson-ci-day-1/</link>
		<comments>http://www.caktusgroup.com/blog/2010/03/08/django-and-hudson-ci-day-1/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 15:58:48 +0000</pubDate>
		<dc:creator>Colin Copeland</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[continuous integration]]></category>

		<category><![CDATA[coverage]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[hudsonci]]></category>

		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=385</guid>
		<description><![CDATA[We&#8217;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 [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re always looking for new tools to make our development environment more robust here at Caktus. We write a lot of <a href="http://www.caktusgroup.com/blog/2009/05/26/testing-django-views-for-concurrency-issues/">tests</a> to ensure proper functionality as new features land and bug fixes are added to our projects. The next step is to integrate with a <a href="http://en.wikipedia.org/wiki/Continuous_integration">continuous integration</a> system to automate the process and regularly check that status of the build.</p>
<p>After attending Dr. C. Titus Brown&#8217;s <a href="http://us.pycon.org/2010/conference/schedule/event/109/">&#8220;Why not run all your tests all the time? A study of continuous integration systems.&#8221;</a> talk at Pycon and seeing <a href="http://hudson.djangoproject.com">Django&#8217;s Hudson setup</a>, I figured I&#8217;d take a look at <a href="http://hudson-ci.org/">Hudson CI</a>.</p>
<h2>Installing Hudson and basic setup</h2>
<p>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 <a href="http://hudson-ci.org/debian/">Debian</a> setup instructions, which basically consists of:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">-O</span> - http:<span style="color: #000000; font-weight: bold;">//</span>hudson-ci.org<span style="color: #000000; font-weight: bold;">/</span>debian<span style="color: #000000; font-weight: bold;">/</span>hudson-ci.org.key | <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-key</span> add -
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;deb http://hudson-ci.org/debian binary/&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>apt<span style="color: #000000; font-weight: bold;">/</span>sources.list
$ <span style="color: #c20cb9; font-weight: bold;">apt-get</span> update
$ <span style="color: #c20cb9; font-weight: bold;">aptitude</span> <span style="color: #c20cb9; font-weight: bold;">install</span> hudson
$ <span style="color: #c20cb9; font-weight: bold;">apt-get</span> upgrade</pre></div></div>

<p>That&#8217;s it! It&#8217;s already up and running on port 8080 using it&#8217;s own web server. Go ahead and pull it up in your browser.</p>
<p>As a test, let&#8217;s setup <a href="http://code.google.com/p/django-crm/">django-crm</a> (a Caktus open-source <a href="http://www.caktusgroup.com/portfolio/community/">community project</a>) as our first Hudson job. Click &#8220;New Job&#8221;, type in a job name, click &#8220;Build a free-style software project&#8221;, and hit OK. django-crm contains a sample project that we&#8217;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:<br />
<a href="http://www.caktusgroup.com/blog/wp-content/uploads/2010/03/hudson-repo.png"><img src="http://www.caktusgroup.com/blog/wp-content/uploads/2010/03/hudson-repo.png" alt="" title="hudson-repo" width="500" height="126" class="aligncenter size-full wp-image-387" /></a></p>
<p>Click Save, run the job by clicking &#8220;Build Now&#8221;, and check out the Console Output:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">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</pre></div></div>

<p>Cool, now let&#8217;s run some tests. Too keep things simple, let&#8217;s grab Django and a few dependencies using aptitude:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>www.djangoproject.com<span style="color: #000000; font-weight: bold;">/</span>download<span style="color: #000000; font-weight: bold;">/</span>1.1.1<span style="color: #000000; font-weight: bold;">/</span>tarball<span style="color: #000000; font-weight: bold;">/</span>
$ <span style="color: #c20cb9; font-weight: bold;">tar</span> xzvf Django-1.1.1.tar.gz
$ <span style="color: #7a0874; font-weight: bold;">cd</span> Django-1.1.1
$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> python setup.py <span style="color: #c20cb9; font-weight: bold;">install</span>
$ <span style="color: #c20cb9; font-weight: bold;">aptitude</span> <span style="color: #c20cb9; font-weight: bold;">install</span> python-dev python-imaging python-setuptools python-pip</pre></div></div>

<p>To run the tests, add an &#8220;Execute shell&#8221; build step in the Build section with this command:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash -ex</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> sample_project
python manage.py <span style="color: #7a0874; font-weight: bold;">test</span> crm</pre></div></div>

<p>Run the job again and look for the test results in the console output:</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">[workspace] $ /bin/sh -xe /tmp/hudson6670261053226891793.sh
+ cd sample_project
+ python manage.py test crm
...
Finished: SUCCESS</pre></div></div>

<h2>XML Test output</h2>
<p>To integrate Hudson with the Django test suite, I used <a href="http://github.com/danielfm/unittest-xml-reporting">unittest-xml-reporting</a>. Just &#8220;pip install unittest-xml-reporting&#8221; and add the following lines to your settings file:</p>

<div class="wp_syntax"><div class="code"><pre class="python python" style="font-family:monospace;">TEST_RUNNER = <span style="color: #483d8b;">'xmlrunner.extra.djangotestrunner.run_tests'</span>
TEST_OUTPUT_VERBOSE = <span style="color: #008000;">True</span>
TEST_OUTPUT_DESCRIPTIONS = <span style="color: #008000;">True</span>
TEST_OUTPUT_DIR = <span style="color: #483d8b;">'xmlrunner'</span></pre></div></div>

<p>Then check &#8220;Publish JUnit test result report&#8221; in the Post-build Actions section and add the path to the test XML output &#8220;sample_project/xmlrunner/*.xml&#8221;:<br />
<a href="http://www.caktusgroup.com/blog/wp-content/uploads/2010/03/test-xml.png"><img src="http://www.caktusgroup.com/blog/wp-content/uploads/2010/03/test-xml.png" alt="" title="test-xml" width="331" height="154" class="aligncenter size-full wp-image-388" /></a></p>
<p>Run the job and you should see a new &#8220;Test Result&#8221; link in the navigation. Now you can view the test results right in your browser window.</p>
<h2>Coverage</h2>
<p>To add coverage reports, I used Ned Batchelder&#8217;s <a href="http://nedbatchelder.com/code/coverage/">coverage.py</a> (pip install coverage). Navigate to Hudson&#8217;s plugin manager (Hudson -> Manage Hudson -> Manage Plugins), install the Cobertura Plugin, and restart Hudson when prompted. Then modify your shell script like so:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash -ex</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> sample_project
coverage run manage.py <span style="color: #7a0874; font-weight: bold;">test</span> crm
coverage xml --<span style="color: #007800;">omit</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>This will generate an XML coverage report in the working directory, so we just need to tell Hudson where to look for it. Check &#8220;Publish Cobertura Coverage Report&#8221; in the Post-build Actions section and enter the path to the report:<br />
<a href="http://www.caktusgroup.com/blog/wp-content/uploads/2010/03/cobertura.png"><img src="http://www.caktusgroup.com/blog/wp-content/uploads/2010/03/cobertura.png" alt="" title="cobertura" width="310" height="108" class="aligncenter size-full wp-image-389" /></a></p>
<p>Run the build again and you should have access to a new &#8220;Coverage Report&#8221; link. </p>
<h2>More to come&#8230;</h2>
<p>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), <a href="http://pypi.python.org/pypi/pep8">check for PEP compliance</a>, and setup build failure notifications. I hope to write more as I continue to setup our Hudson environment!</p>
<h3>References</h3>
<p>A few useful Hudson/Python/Django links I discovered while running through this setup:</p>
<ul>
<li><a href="http://guyofgisbourne.blogspot.com/2009/02/django-and-hudson-and-bears-oh-my-and.html">Django and Hudson and Bears, Oh My! (and twill, and figleaf)</a></li>
<li><a href="http://www.rhonabwy.com/wp/2009/11/04/setting-up-a-python-ci-server-with-hudson/">Setting up a python CI server with Hudson</a></li>
<li><a href="http://heisel.org/blog/2009/11/21/django-hudson/">Django continuous integration with Hudson and Nose</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2010/03/08/django-and-hudson-ci-day-1/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Caktus Sends Team of Five to PyCon 2010 in Atlanta</title>
		<link>http://www.caktusgroup.com/blog/2010/02/17/caktus-sends-team-of-five-to-pycon-2010-in-atlanta/</link>
		<comments>http://www.caktusgroup.com/blog/2010/02/17/caktus-sends-team-of-five-to-pycon-2010-in-atlanta/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 18:08:30 +0000</pubDate>
		<dc:creator>tobias</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[pycon]]></category>

		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=376</guid>
		<description><![CDATA[Python and Django are tools we use on a daily basis to build fantastic web apps here at Caktus.  I&#8217;m pleased to announce that Caktus is sending five developers&#8211;Colin, Alex, Mike, Mark, and myself&#8211;to PyCon 2010!  PyCon is an annual gathering for users and developers of the open source Python programming language.  [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.python.org">Python</a> and <a href="http://www.djangoproject.org">Django</a> are tools we use on a daily basis to build <a href="http://www.caktusgroup.com/services/">fantastic web apps</a> here at Caktus.  I&#8217;m pleased to announce that Caktus is sending five developers&#8211;Colin, Alex, Mike, Mark, and myself&#8211;to <a href="http://us.pycon.org/2010/about/">PyCon 2010</a>!  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&#8217;ll be driving down tomorrow (Thursday) from Chapel Hill, NC and staying for the conference weekend plus one day of the sprints.</p>
<p><img src="http://www.processmechanics.com/media/pycon2010/attending-pycon2010-400x60.png" alt="I am attending PyCon"/></p>
<p>Hope to see you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2010/02/17/caktus-sends-team-of-five-to-pycon-2010-in-atlanta/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Caktus Consulting Group hosts Django sprint in Triangle, NC area</title>
		<link>http://www.caktusgroup.com/blog/2009/12/06/caktus-consulting-group-hosts-django-sprint-in-triangle-nc-area/</link>
		<comments>http://www.caktusgroup.com/blog/2009/12/06/caktus-consulting-group-hosts-django-sprint-in-triangle-nc-area/#comments</comments>
		<pubDate>Sun, 06 Dec 2009 19:37:17 +0000</pubDate>
		<dc:creator>tobias</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[django]]></category>

		<category><![CDATA[open source]]></category>

		<category><![CDATA[sprint]]></category>

		<guid isPermaLink="false">http://www.caktusgroup.com/blog/?p=369</guid>
		<description><![CDATA[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&#8217;re proud to annouce that Caktus is hosting a local Django development sprint in [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.djangoproject.com/">Django</a> is a tool we use every day to build <a href="http://www.caktusgroup.com/services/">rock-solid web apps</a> 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.</p>
<p>We&#8217;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 <a href="http://carrborocoworking.com/">Carrboro Creative Coworking</a>, and the purpose of this sprint will be to help finish features and push out bug fixes in preparation for the upcoming <a href="http://code.djangoproject.com/wiki/Version1.2Features">Django 1.2 release</a>.</p>
<p>If you&#8217;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 <a href="http://code.djangoproject.com/wiki/Sprint200912TriangleNC">corresponding wiki page</a> and don&#8217;t forget to <a href="http://django-triangle-dec-09.eventbrite.com/">register for the event</a>.</p>
<p>We&#8217;ll be there to open the doors at 9am both days.  Courtesy of our <a href="http://code.djangoproject.com/wiki/Sprint200912TriangleNC#Sponsors">sponsors</a> there will be free drinks, snacks, and lunch to go around.  Hope to see you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caktusgroup.com/blog/2009/12/06/caktus-consulting-group-hosts-django-sprint-in-triangle-nc-area/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
