<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Re-Cycled Air</title>
	<atom:link href="http://www.re-cycledair.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.re-cycledair.com</link>
	<description>Jack Slingerland&#039;s Programming Adventures</description>
	<lastBuildDate>Tue, 14 May 2013 12:46:16 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Requirements</title>
		<link>http://www.re-cycledair.com/requirements</link>
		<comments>http://www.re-cycledair.com/requirements#comments</comments>
		<pubDate>Tue, 14 May 2013 12:46:16 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1540</guid>
		<description><![CDATA[There is a grand myth about requirements&#8211;if you write them down, users will get exactly what they want. That&#8217;s not true. At best, users will get exactly what was written down, which may or may not be anything like what they really want. - Mike Cohn, &#8220;Succeeding with Agile&#8221;]]></description>
				<content:encoded><![CDATA[<blockquote><p>
There is a grand myth about requirements&#8211;if you write them down, users will get exactly what they want.  That&#8217;s not true.  At best, users will get exactly what was written down, which may or may not be anything like what they really want.<br />
- Mike Cohn, &#8220;Succeeding with Agile&#8221;
</p></blockquote>
 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1540" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/requirements/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Saving within a post_save signal in Django</title>
		<link>http://www.re-cycledair.com/saving-within-a-post_save-signal-in-django</link>
		<comments>http://www.re-cycledair.com/saving-within-a-post_save-signal-in-django#comments</comments>
		<pubDate>Wed, 24 Apr 2013 17:13:57 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[post_save]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[signals]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1532</guid>
		<description><![CDATA[One of the more useful features of the Django framework is it&#8217;s extensive signaling capabilities. The ORM throws off a handful of signals every time a model is initialized, modified, saved, or deleted. They include: pre_init post_init pre_save post_save pre_delete post_delete m2m_changed class_prepared I tend to use the post_save signal fairly often as a good [...]]]></description>
				<content:encoded><![CDATA[<p>One of the more useful features of the Django framework is it&#8217;s extensive signaling capabilities.  The ORM throws off a handful of signals every time a model is initialized, modified, saved, or deleted.  They include:</p>
<ul>
<li>pre_init</li>
<li>post_init</li>
<li>pre_save</li>
<li>post_save</li>
<li>pre_delete</li>
<li>post_delete</li>
<li>m2m_changed</li>
<li>class_prepared</li>
</ul>
<p>I tend to use the post_save signal fairly often as a good way to get around overriding the default save method on models.  Recently though I ran into an issue where I was hitting the &#8220;maximum recursion depth exceeded&#8221; error when I was saving the current model from within the post_save signal.  If you think about it, that makes a lot of sense.  You save once, then save again in the signal and then it triggers the signal again.  <strong>BOOM</strong>, infinite loop.</p>
<p>To get around the saving within a post_save signal problem, you just need to disconnect the post_save signal before you call save.  After save, you can re-connect it.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> signals
signals.<span style="color: black;">post_save</span>.<span style="color: black;">disconnect</span><span style="color: black;">&#40;</span>some_method<span style="color: #66cc66;">,</span> sender<span style="color: #66cc66;">=</span>SomeModel<span style="color: black;">&#41;</span>
some_instance.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
signals.<span style="color: black;">post_save</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>some_method<span style="color: #66cc66;">,</span> sender<span style="color: #66cc66;">=</span>SomeModel<span style="color: black;">&#41;</span></pre></td></tr></table></div>

 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1532" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/saving-within-a-post_save-signal-in-django/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Programmatically Adding Users to Groups in Django</title>
		<link>http://www.re-cycledair.com/programmatically-adding-users-to-groups-in-django</link>
		<comments>http://www.re-cycledair.com/programmatically-adding-users-to-groups-in-django#comments</comments>
		<pubDate>Thu, 21 Mar 2013 17:30:57 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1524</guid>
		<description><![CDATA[I recently needed to add a large number of users to a permission group in Django. I had a hard time finding a way to do this in the documentation, so I thought I&#8217;d share my solution. from django.contrib.auth.models import Group, User &#160; g = Group.objects.get&#40;name='My Group Name'&#41; users = User.objects.all&#40;&#41; for u in users: [...]]]></description>
				<content:encoded><![CDATA[<p>I recently needed to add a large number of users to a permission group in Django.  I had a hard time finding a way to do this in the documentation, so I thought I&#8217;d share my solution.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="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;">auth</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Group<span style="color: #66cc66;">,</span> User
&nbsp;
g <span style="color: #66cc66;">=</span> Group.<span style="color: black;">objects</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'My Group Name'</span><span style="color: black;">&#41;</span>
users <span style="color: #66cc66;">=</span> User.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> u <span style="color: #ff7700;font-weight:bold;">in</span> users:
    g.<span style="color: black;">user_set</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span>u<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Easy as pie.  I originally attempted to do this from the perspective of a user, but as it turns out, doing it from the group perspective is much easier.</p>
 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1524" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/programmatically-adding-users-to-groups-in-django/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Copying Django Model Objects</title>
		<link>http://www.re-cycledair.com/copying-django-model-objects</link>
		<comments>http://www.re-cycledair.com/copying-django-model-objects#comments</comments>
		<pubDate>Fri, 08 Mar 2013 12:54:08 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1490</guid>
		<description><![CDATA[Django&#8217;s ORM is top notch. It provides facilities to do almost anything you can think of with a database, and if it doesn&#8217;t, it still lets you execute arbitrary SQL to your hearts content. I&#8217;ve been developing Django for close to 2 years now, and still discover facets of it that I never knew existed. [...]]]></description>
				<content:encoded><![CDATA[<p>Django&#8217;s ORM is top notch.  It provides facilities to do almost anything you can think of with a database, and if it doesn&#8217;t, it still lets you execute arbitrary SQL to your hearts content.  I&#8217;ve been developing Django for close to 2 years now, and still discover facets of it that I never knew existed.  For instance, I had a need to duplicate a row in a table, but give it a different primary key.  After a quick Google search, I discovered that Django allows you to do the following to copy instantiated model objects.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">my_model <span style="color: #66cc66;">=</span> MyModel.<span style="color: black;">objects</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>pk<span style="color: #66cc66;">=</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>
my_model.<span style="color: #008000;">id</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span>
my_model.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>There are a few caveats with doing things this way.</p>
<ul>
<li><strong>Unique Constraints</strong> &#8211; If you have any unique constraints on the model, the save will not pass validation and fail.</li>
<li><strong>ManyToMany Fields</strong> &#8211; If you need new copies of ManyToMany field values, you&#8217;ll need to handle this yourself.</li>
</ul>
<p>That being said, in many cases duplicating a model instance is as easy as changing it&#8217;s ID and saving.</p>
 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1490" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/copying-django-model-objects/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Update All PIP Packages</title>
		<link>http://www.re-cycledair.com/update-all-pip-packages</link>
		<comments>http://www.re-cycledair.com/update-all-pip-packages#comments</comments>
		<pubDate>Tue, 12 Feb 2013 04:08:34 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[pip]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1496</guid>
		<description><![CDATA[Revisiting an old Python + Django project made me realize that I needed to upgrade it&#8217;s PIP packages. Unfortunately, PIP doesn&#8217;t provide a way out of the box to update all of your installed packages at once. To update all of the PIP packages at once, use the following script. import pip from subprocess import [...]]]></description>
				<content:encoded><![CDATA[<p>Revisiting an old Python + Django project made me realize that I needed to upgrade it&#8217;s PIP packages.  Unfortunately, PIP doesn&#8217;t provide a way out of the box to update all of your installed packages at once.  To update all of the PIP packages at once, use the following script.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> pip
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">subprocess</span> <span style="color: #ff7700;font-weight:bold;">import</span> call
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> dist <span style="color: #ff7700;font-weight:bold;">in</span> pip.<span style="color: black;">get_installed_distributions</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    call<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pip install --upgrade &quot;</span> + dist.<span style="color: black;">project_name</span><span style="color: #66cc66;">,</span> shell<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>For more detail, check out <a href='http://stackoverflow.com/questions/2720014/upgrading-all-packages-with-pip/5839291#5839291'>this</a> question on Stack Overflow.</p>
 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1496" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/update-all-pip-packages/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>28 Questions</title>
		<link>http://www.re-cycledair.com/28-questions</link>
		<comments>http://www.re-cycledair.com/28-questions#comments</comments>
		<pubDate>Wed, 09 Jan 2013 17:24:21 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[startups]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1482</guid>
		<description><![CDATA[Over the past few years I&#8217;ve tried my hand at launching a couple of different start ups. Over this time period, I&#8217;ve collected a set of questions from many different sources (HN, YCombinator, TechStars, etc) that I ask myself before proceeding. They help be decided if this is a real or manufactured problem, if it [...]]]></description>
				<content:encoded><![CDATA[<p>Over the past few years I&#8217;ve tried my hand at launching a couple of different start ups.  Over this time period, I&#8217;ve collected a set of questions from many different sources (HN, YCombinator, TechStars, etc) that I ask myself before proceeding.  They help be decided if this is a real or manufactured problem, if it can be profitable, and if people will buy what I&#8217;m selling.  My latest project idea is the only idea I&#8217;ve had that passes all of these questions to my satisfaction.  How do yours hold up?</p>
<ol>
<li>What are you going to build?</li>
<li>What is the actual problem?</li>
<li>How will you sell your product/service?</li>
<li>What are some potential obstacles?</li>
<li>What are some existing options that solve this problem? How are you different?</li>
<li>Who needs what you&#8217;re making?</li>
<li>How do you know that they need it?</li>
<li>How is the problem being solved now? Is it being solved now?</li>
<li>Why isn&#8217;t this being done your way already?</li>
<li>How will customers find out about you?</li>
<li>What resistance will they have to trying your product?</li>
<li>What are some key things about your project that outsiders don&#8217;t understand?</li>
<li>Who will your first paying customer be?</li>
<li>How might you expand if your initial idea succeeds?</li>
<li>Why did you choose to work on this idea?</li>
<li>Six months from now, what will be you biggest problem?</li>
<li>What are the hard parts of this idea?</li>
<li>Who would you hire/add to your team?</li>
<li>What is the next step in product evolution?</li>
<li>How does your product work?</li>
<li>How big is the opportunity? [market]</li>
<li>How do you know customers need what you&#8217;re making?</li>
<li>What domain expertise do you have?  Why should you be the one to do this?</li>
<li>What part of your project will you build first? (could be business connections, hardware, software, etc)</li>
<li>How much money could you make per year?</li>
<li>How will you make money?</li>
<li>What have you built in the past?</li>
<li>How would you spend $5,000, how would you use it?</li>
</ol>
 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1482" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/28-questions/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing Local Flavor with Django 1.5</title>
		<link>http://www.re-cycledair.com/installing-local-flavor-with-django-1-5</link>
		<comments>http://www.re-cycledair.com/installing-local-flavor-with-django-1-5#comments</comments>
		<pubDate>Sat, 05 Jan 2013 15:28:27 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[django 1.5]]></category>
		<category><![CDATA[pip]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1477</guid>
		<description><![CDATA[I just started a new project using the latest release candidate of Django 1.5. One thing that I needed was the local flavor add-on so I could get a list of US states. This functionality used to be rolled into the main codebase, but it was rightfully removed in Django 1.5. To install the US [...]]]></description>
				<content:encoded><![CDATA[<p>I just started a new project using the latest release candidate of Django 1.5.  One thing that I needed was the local flavor add-on so I could get a list of US states.  This functionality used to be rolled into the main codebase, but it was rightfully removed in Django 1.5.  To install the US local flavor package, just use PIP.</p>
<pre>
pip install https://github.com/django/django-localflavor-us/zipball/master
</pre>
<p>Now you should be able to import anything you need from the package in the usual manner, except from the new package instead of the old one.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django_localflavor_us.<span style="color: black;">us_states</span> <span style="color: #ff7700;font-weight:bold;">import</span> STATE_CHOICES</pre></td></tr></table></div>

<p>For more information, check out the <a href='https://docs.djangoproject.com/en/dev/ref/contrib/localflavor/#how-to-migrate'>How To Migrate</a> section of the local flavor docs on the Django documentation site.</p>
 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1477" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/installing-local-flavor-with-django-1-5/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extending Django&#8217;s Model.save() Method</title>
		<link>http://www.re-cycledair.com/extending-djangos-model-save-method</link>
		<comments>http://www.re-cycledair.com/extending-djangos-model-save-method#comments</comments>
		<pubDate>Mon, 26 Nov 2012 00:42:32 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1466</guid>
		<description><![CDATA[I&#8217;m currently working on a project where I have a model named &#8216;Instructor&#8217; with a few fields: first_name &#8211; CharField last_name &#8211; CharField departments &#8211; Many-toMany I found out at some point that I&#8217;d really like a field called &#8220;full_name&#8221;, which is &#8220;first_name&#8221; and &#8220;last_name&#8221; concatenated together. I didn&#8217;t want to have to fill the [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m currently working on a project where I have a model named &#8216;Instructor&#8217; with a few fields:</p>
<ul>
<li>first_name &#8211; CharField</li>
<li>last_name &#8211; CharField</li>
<li>departments &#8211; Many-toMany</li>
</ul>
<p>I found out at some point that I&#8217;d really like a field called &#8220;full_name&#8221;, which is &#8220;first_name&#8221; and &#8220;last_name&#8221; concatenated together.  I didn&#8217;t want to have to fill the field in though, I wanted it to happen automatically.  To accomplish this, I extended Django&#8217;s Model.save() method after I added the &#8216;full_name&#8217; column to my model.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Instructor<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    first_name <span style="color: #66cc66;">=</span> models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length<span style="color: #66cc66;">=</span><span style="color: #ff4500;">150</span><span style="color: black;">&#41;</span>
    last_name <span style="color: #66cc66;">=</span> models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length<span style="color: #66cc66;">=</span><span style="color: #ff4500;">150</span><span style="color: black;">&#41;</span>
    departments <span style="color: #66cc66;">=</span> models.<span style="color: black;">ManyToManyField</span><span style="color: black;">&#40;</span>Department<span style="color: black;">&#41;</span>
    full_name <span style="color: #66cc66;">=</span> models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length<span style="color: #66cc66;">=</span><span style="color: #ff4500;">180</span><span style="color: #66cc66;">,</span> blank<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> save<span style="color: black;">&#40;</span> <span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kw <span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">full_name</span> <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'{0} {1}'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>.<span style="color: black;">first_name</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">last_name</span> <span style="color: black;">&#41;</span>
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span> Instructor<span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span> <span style="color: black;">&#41;</span>.<span style="color: black;">save</span><span style="color: black;">&#40;</span> *args<span style="color: #66cc66;">,</span> **kw <span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>And that&#8217;s it!  Now every time I create a new instructor with &#8216;first_name&#8217; and &#8216;last_name&#8217;, it automatically populates the &#8216;full_name&#8217; field for me.</p>
 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1466" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/extending-djangos-model-save-method/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deploying Django with Fabric</title>
		<link>http://www.re-cycledair.com/deploying-django-with-fabric</link>
		<comments>http://www.re-cycledair.com/deploying-django-with-fabric#comments</comments>
		<pubDate>Mon, 20 Aug 2012 14:46:18 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[fabric]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1412</guid>
		<description><![CDATA[Fabric is a Python library and command-line tool for streamlining the use of SSH to deployment and sys-admin tasks. In the Django community Fabric has been picked up as the de facto standard for deploying apps, which is a place that it deserves. One thing I noticed though was that there wasn&#8217;t a lot of [...]]]></description>
				<content:encoded><![CDATA[<p>Fabric is a Python library and command-line tool for streamlining the use of SSH to deployment and sys-admin tasks.  In the Django community Fabric has been picked up as the de facto standard for deploying apps, which is a place that it deserves.  One thing I noticed though was that there wasn&#8217;t a lot of good examples for getting it to place nice with VirtualEnv.</p>
<h2>Getting Started</h2>
<p>The first thing you need is to make sure that you have Fabric installed. </p>
<pre>
pip install fabric
</pre>
<p>Once that&#8217;s done, open a file called <em>fabfile.py</em> and add the following imports:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> with_statement
<span style="color: #ff7700;font-weight:bold;">from</span> fabric.<span style="color: black;">api</span> <span style="color: #ff7700;font-weight:bold;">import</span> *</pre></td></tr></table></div>

<h2>Role Defs</h2>
<p>Fabric has two functions that get used <u>very</u> frequently: local &amp; run.  The local() command will execute whatever you pass into in your local environment.  The run() command will execute whatever you put into it in a remote environment defined in your roledefs.</p>
<p>A roledef defines a what a server is.  For instance, if you have a nice fleshed out dev-staging-live type of environment:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">evn.<span style="color: black;">roledefs</span> <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span>
	<span style="color: #483d8b;">'dev'</span> : <span style="color: black;">&#91;</span><span style="color: #483d8b;">'dev.re-cycledair.com'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
	<span style="color: #483d8b;">'staging'</span> : <span style="color: black;">&#91;</span><span style="color: #483d8b;">'staging.re-cycledair.com'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
	<span style="color: #483d8b;">'live'</span> : <span style="color: black;">&#91;</span><span style="color: #483d8b;">'re-cycledair.com'</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#125;</span></pre></td></tr></table></div>

<p>Once your roledefs are defined, you can run code on those specific servers by using the <em>@roles</em> decorator.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>roles<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dev&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> ls_on_dev:
	run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;ls&quot;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Runs 'ls' on dev.re-cycledair.com</span>
&nbsp;
<span style="color: #66cc66;">@</span>roles<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;staging&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> ls_on_staging:
	run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;ls&quot;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Runs 'ls' on staging.re-cycledair.com</span></pre></td></tr></table></div>

<p>At this point, you want to run one of your new Fabric functions, from the directory where your fabfile is run:</p>
<pre>
fab ls_on_staging
</pre>
<h2>Deployment</h2>
<p>Now that you&#8217;ve got a handle on the trivial examples, lets make things a little more useful.  We&#8217;re going to deploy to our &#8216;staging&#8217; server.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>roles<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;staging&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> deploy_staging<span style="color: black;">&#40;</span>tag<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
	code_dir <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'/path/to/remote/directory'</span>
	<span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">cd</span><span style="color: black;">&#40;</span>code_dir<span style="color: black;">&#41;</span>:
		run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;git fetch&quot;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> tag:
			run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;git checkout %s&quot;</span> % tag<span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;git checkout master&quot;</span><span style="color: black;">&#41;</span>
			run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;git pull origin master&quot;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">with</span> prefix<span style="color: black;">&#40;</span><span style="color: #483d8b;">'source /path/to/virtual/environment/bin/activate'</span><span style="color: black;">&#41;</span>:
			run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pip install -r requirements.txt&quot;</span><span style="color: black;">&#41;</span>
			run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;python manage.py syncdb&quot;</span><span style="color: black;">&#41;</span>
			run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;python manage.py migrate&quot;</span><span style="color: black;">&#41;</span>
			run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;python manage.py collectstatic --noinput&quot;</span><span style="color: black;">&#41;</span>
			run<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;touch path/to/wsgi.py&quot;</span></pre></td></tr></table></div>

<p>All this code is pretty self-explanatory.  The <em>@roles</em> decorator has run execute in the context of &#8220;staging&#8221;.  The run commands are just regular commands you would execute at the terminal if you were manually deploying.  The only potential &#8220;gotch-ya&#8221; is the <em>with prefix</em> call.  That basically says &#8220;execute the following statements in the context of my virtual environment&#8221;.  To make everthing go:</p>
<pre>
fab deploy_staging
</pre>
<p>will deploy the head of the master branch and</p>
<pre>
fab deploy_staging:tag=1.0.0
</pre>
<p>will deploy the 1.0.0 tag.</p>
<h2>Done</h2>
<p>If all goes well, you can now deploy your app in seconds!  If it takes longer then that, you might need to set up your ssh keys you so can login to your server without getting prompted for usernames and password.</p>
 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1412" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/deploying-django-with-fabric/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deploying Django 1.4 to Heroku</title>
		<link>http://www.re-cycledair.com/deploying-django-1-4-to-heroku</link>
		<comments>http://www.re-cycledair.com/deploying-django-1-4-to-heroku#comments</comments>
		<pubDate>Sat, 28 Apr 2012 12:45:50 +0000</pubDate>
		<dc:creator>Jack Slingerland</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.re-cycledair.com/?p=1367</guid>
		<description><![CDATA[Note: It is assumed that your are keeping track of your changes using Git. If you aren&#8217;t, you&#8217;ll need to be to deploy to Heroku. If there is one thing that scares beginners away from Django, its the idea of deployment. For a PHP programmer, deployment can be as simple as FTP&#8217;ing some files to [...]]]></description>
				<content:encoded><![CDATA[<p><em>Note: It is assumed that your are keeping track of your changes using Git.  If you aren&#8217;t, you&#8217;ll need to be to deploy to Heroku.</em></p>
<p>If there is one thing that scares beginners away from Django, its the idea of deployment.  For a PHP programmer, deployment can be as simple as FTP&#8217;ing some files to a server, and boom, deployed.  This isn&#8217;t to say that PHP deployment is simple.  If you have to do it from scratch (get apache running, get your db installed, get PHP installed and configured, etc, etc) it can still be very complex, but many hosting companies take care of this for you.  It&#8217;s almost like you never even have to think about it, which isn&#8217;t always the case for Django.  That doesn&#8217;t mean its a bad thing, just&#8230;<em>different</em>.</p>
<p>So where do we start?  Heroku is as good a place as any.</p>
<h2>Heroku</h2>
<p><a href="http://www.re-cycledair.com/wp-content/uploads/2012/04/heroku-Logo-1.jpg" rel="lightbox[1367]"><img src="http://www.re-cycledair.com/wp-content/uploads/2012/04/heroku-Logo-1-300x93.jpg" alt="" title="Heroku Logo" width="300" height="93" class="aligncenter size-medium wp-image-1368" /></a><br />
<a href='http://www.heroku.com'>Heroku</a> is a cloud service for easy deployment of web applications.  Initially it was Ruby only, but has been working hard to become a deployment service for many languages including Java, Python, and Node.js.  Deploying to Heroku assumes a few things:</p>
<ol>
<li>You are familiar with Git and use it to track your code changes.</li>
<li>You are at least passingly familiar with PostgreSQL, because that&#8217;s what you will being using. (You can use other storage devices, but PostgreSQL is the default and easiest to setup.</li>
<li>You use PIP to manage your project&#8217;s requirements.  If you aren&#8217;t doing this, you need to be. (seriously, it&#8217;s worth the effort)</li>
</ol>
<p>Now that we have that out of the way, let&#8217;s get started.  Before we can proceed further, you&#8217;ll need to get a Heroku account set up.  For our testing purposes, a free account should be plenty.</p>
<ol>
<li>Go to <a href='http://www.heroku.com'>Heroku.com</a> and set up an account.</li>
<li>Go to <a href='https://toolbelt.herokuapp.com'>https://toolbelt.herokuapp.com</a> and download the Herok toolbelt.  Follow the directions on this page up to the &#8220;login&#8221; section.</li>
</ol>
<p>That&#8217;s all for setting up Heroku for now.  Next, we&#8217;re going to move on to configure Django so it can be deployed.</p>
<h2>Django</h2>
<p>Django gives you the flexibility to use almost any database under the sun.  I generally develop using MySQL, but Heroku uses Postgres.  As long as you haven&#8217;t been hand-tailoring queries, this shouldn&#8217;t provide any problem whatsoever.  To make your project compatible with Heroku, you need to install the <strong>psycopg2</strong> library.</p>
<pre>
pip install psycopg2
</pre>
<p>Now that you have the Postgres library installed, when your app is pushed to Heroku, Heroku will append some code to the end of your <em>settings.py</em> file that will point your install to the correct database.</p>
<p>Speaking of <em>settings.py</em>, you&#8217;ll also need to get your template and media paths set up correctly.  To do that, add the following to the top of your <em>settings.py</em> and then set your paths to look like this:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>
root <span style="color: #66cc66;">=</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;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\\</span>'</span><span style="color: #66cc66;">,</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>
&nbsp;
MEDIA_ROOT <span style="color: #66cc66;">=</span> root + <span style="color: #483d8b;">'/../media/'</span>
STATIC_ROOT <span style="color: #66cc66;">=</span> root + <span style="color: #483d8b;">'/../static/'</span>
TEMPLATE_DIRS <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>
    root +<span style="color: #483d8b;">'/../templates'</span><span style="color: #66cc66;">,</span>
<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>We use this calculate root variable because it&#8217;s kind of a pain to know the path of your install on Heroku.  This way it doesn&#8217;t matter where you deploy your app to, it should just work.  Another thing to consider is static files.  Heroku can be made to serve them, but having the same domain that is serving your site serve your static files is bad practice.</p>
<h2>Wrapping it up</h2>
<p>Now that Django is configured for Heroku deployment, all that&#8217;s left is to deploy it!  The first thing we need to do is create a requirements file so that Heroku knows what packages to install.  At the top level of your project, run the following:</p>
<pre>
pip freeze > requirements.txt
</pre>
<p>Great, now if you look at the generated file you can see what software Heroku is going to install for you.  Next up, we&#8217;re going to create an app on Heroku (assuming you set up the Heroku tool belt correctly).  In the top level directory of your project, run the following.</p>
<pre>
heroku create --stack cedar
</pre>
<p>This added your new Heroku app as a remote on your local Git repository.  All you do to deploy is:</p>
<pre>
git push heroku master
</pre>
<p>Which should give you some output that looks like:</p>
<pre>
Counting objects: 10, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (10/10), 3.59 KiB, done.
Total 10 (delta 0), reused 0 (delta 0)

-----> Heroku receiving push
-----> Python/Django app detected
-----> Preparing Python interpreter (2.7.2)
-----> Creating Virtualenv version 1.7
       New python executable in .heroku/venv/bin/python2.7
       Also creating executable in .heroku/venv/bin/python
       Installing distribute........done.
       Installing pip...............done.
       Running virtualenv with interpreter /usr/local/bin/python2.7
-----> Activating virtualenv
-----> Installing dependencies using Pip version 1.0.2
       Downloading/unpacking Django==1.4 (from -r requirements.txt (line 1))
       ...
       Successfully installed Django psycopg2
       Cleaning up...
-----> Injecting Django settings...
       Injecting code into ./hellodjango/settings.py to read from DATABASE_URL
-----> Discovering process types
       Procfile declares types         -> (none)
       Default types for Python/Django -> web
-----> Compiled slug size is 9.3MB
-----> Launching... done, v4
       http://simple-spring-9999.herokuapp.com deployed to Heroku

To git@heroku.com:afternoon-sword-29.git
* [new branch]      master -> master
</pre>
<p>On the line immediately after &#8220;&#8212;&#8211;> Launching&#8230; done,&#8230;&#8221;, the url of your project is displayed.  Before you go to it though, you need to run syncdb on Heroku.  The Heroku toolbelt makes this pretty easy:</p>
<pre>
heroku run python manage.py syncdb
</pre>
<h2>Conclusion</h2>
<p>That&#8217;s all there is to it.  If you get stuck, feel free to leave a comment.  Heroku also has a great guide for getting up and running and explains some more features of the Heroku tool belt.  That can be found <a href='https://devcenter.heroku.com/articles/django'>here</a>.</p>
 <img src="http://www.re-cycledair.com/?feed-stats-post-id=1367" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.re-cycledair.com/deploying-django-1-4-to-heroku/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced
Database Caching 3/7 queries in 0.045 seconds using disk
Object Caching 637/647 objects using disk

 Served from: www.re-cycledair.com @ 2013-05-21 20:56:30 by W3 Total Cache -->