<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>gregbrown.co.nz</title><link>http://gregbrown.co.nz/</link><description>Latest additions to gregbrown.co.nz</description><language>en-us</language><lastBuildDate>Thu, 11 Nov 2010 10:33:07 +1300</lastBuildDate><feedburner:info uri="gregbrown" /><feedburner:info uri="gregbrown" /><feedburner:info uri="gregbrown" /><feedburner:emailServiceId>gregbrown</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/gregbrown" /><feedburner:info uri="gregbrown" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>gregbrown</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><title>Django Simple Migrations</title><link>http://feedproxy.google.com/~r/gregbrown/~3/XaoyfPSTj-k/</link><description>&lt;p&gt;The following is a simple django custom management command to handle model field additions and deletions on a development machine. It automates a common pattern in django development – that of renaming an existing table, recreating via syncdb, and inserting the old data into the new table. Right now it doesn't handle renames, and is only tested using an sqlite backend. With mysql or postgres, I would suggest manually making table changes anyway, since – unlike sqlite – they have that capability.&lt;/p&gt;

&lt;p&gt;If you're after a more comprehensive migration system, I'd recommend &lt;a href="http://south.aeracode.org/"&gt;South&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Download the code at &lt;a href="https://gist.github.com/671593"&gt;https://gist.github.com/671593&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Source Code&lt;/h2&gt;

&lt;script src="https://gist.github.com/671593.js?file=simplemigration.py"&gt;&lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/NN90IkZyVdE" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/fCk_i4Z-ZRQ" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/p-uvRBmuHZg" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/XaoyfPSTj-k" height="1" width="1"/&gt;</description><pubDate>Thu, 11 Nov 2010 10:33:07 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/django-simple-migrations/</guid><feedburner:origLink>http://gregbrown.co.nz/code/django-simple-migrations/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/NN90IkZyVdE/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/fCk_i4Z-ZRQ/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/p-uvRBmuHZg/</feedburner:origLink></item><item><title>Brown-Bier Theorem</title><link>http://feedproxy.google.com/~r/gregbrown/~3/8nBKNOFRiCI/</link><description>&lt;p&gt;&lt;em&gt;This article originally appeared on &lt;a href="http://brehaut.net"&gt;brehaut.net&lt;/a&gt; – thanks to Andrew for providing the content.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Brown's Theorem&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;Q = 1 / k&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The quality of an amp is inversely proportional to the number of knobs it has.&lt;/p&gt;

&lt;p&gt;Following the pioneering work of Greg in this field, Stephen proposed the following postulate in late 2006:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The quality of an amp is proportional to t, the percentage of the amplification done by vacuum tubes rather than transistors.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Which leads to...&lt;/p&gt;

&lt;h3&gt;The Brown-Bier Grand Unified Theorem of Tonal Quality in Amplifiers:&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;Q = t / k&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Violations&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.beavisaudio.com/Projects/FuzzLab/index.htm"&gt;Brown-Bier violation on a grand scale&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.mesaboogie.com/Product_Info/Rectifier_Series/roadking/roadking.htm|"&gt; Good effort with the tubes, but well and truly let down by the knob count...&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://line6.com/vetta_ii/US/images/pictures/vetta2head_front.jpg"&gt;Ahem...&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ehx.com/ehx2/Default.asp?q=f&amp;amp;f=%2FCatalog%2F01%5FNew%5FProducts%2F14%5FFlanger%5FHoax"&gt;Flanger Hoax?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Gear that &lt;em&gt;Gets It&lt;/em&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.soultoneamps.com/18watt/Lon212dart.jpg"&gt;18 Watt Dartanian&lt;/a&gt; (an &lt;em&gt;infinite&lt;/em&gt; Brown-Bier index, no less!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Comments&lt;/h4&gt;

&lt;p&gt;Does anyone else find it funny that if you say Brown-Bier Grand Unified Theorem out loud it sounds like "Brown beer"? Ah, good old the Near/Square merger :D --- christina&lt;/p&gt;

&lt;p&gt;Not really, Bier is the Dutch and German word for Beer so its hardly surprising --- brehaut&lt;/p&gt;

&lt;p&gt;May I also add that I am actually part of a musical duo that writes songs, and we have taken our band name from our surnames - Browne Bier --- stephen&lt;/p&gt;

&lt;p&gt;Greg suggested that the index may need to take into account multiple channels, and whether they are switchable --- brehaut&lt;/p&gt;

&lt;p&gt;Yeah... maybe Q = t / kc where c = number of channels? --- greg&lt;/p&gt;

&lt;p&gt;I feel that we should redefine "k" as the number of knobs that do not have "11" as a maximum possible value. --- angus.&lt;/p&gt;

&lt;p&gt;I propose the following amendment:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;Q = e ? (negative infinity) : (t / k)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;where e = number of knobs that go to 11 &lt;br /&gt;
--- greg&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/LP9sONgoIAQ" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/7tp6OAarlho" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/V4drtdjwV0Q" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/8nBKNOFRiCI" height="1" width="1"/&gt;</description><pubDate>Tue, 14 Sep 2010 12:48:43 +1200</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/misc/brown-bier-theorem/</guid><feedburner:origLink>http://gregbrown.co.nz/misc/brown-bier-theorem/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/LP9sONgoIAQ/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/7tp6OAarlho/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/V4drtdjwV0Q/</feedburner:origLink></item><item><title>Tragedy of the Commons</title><link>http://feedproxy.google.com/~r/gregbrown/~3/gZ0n1Iop_xM/</link><description>&lt;p&gt;&lt;em&gt;This article originally appeared on &lt;a href="http://brehaut.net"&gt;brehaut.net&lt;/a&gt; – thanks to Andrew for providing the content.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Tragedy of the Commons 2005-2006&lt;/h3&gt;

&lt;p&gt;The reign of Tragedy of the Commons as Christchurch's premier orchestrators of musical chaos, while brief, left an indelible mark on the local music scene. Their bombastic musicality and wild theatrics assaulted the senses of fans from Timaru to New Brighton, and inspired legions of skinny emo kids to buy Squier strats and cheap solid-state amplifiers.&lt;/p&gt;

&lt;p&gt;Their notable achievements included victory in the 2005 regional Primal Battle of the Bands, several placings in other competitions, and managing to convince both the Christchurch Polytechnic and the City Council that they were a mellow acoustic band (Captain's Calling anyone?)&lt;/p&gt;

&lt;p&gt;Among their various recordings, ‘Live at Zebedees 2005’ stands out as the quintessential in-your-face indie record of recent times—capturing the TotC live show at its wild, offensive best—with no pretense to mainstream obligations such as studio engineering or gracious behaviour towards one's audience. In its own way, the record epitomised the experimental and alternative mantra of the band, and continues to provide a fitting tribute to the sonic juggernaut that was Tragedy of the Commons. &lt;/p&gt;

&lt;h3&gt;Choice moments in the history of TotC&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Matt B mildly concussing himself by jumping from the bass drum upwards into a concrete beam.&lt;/li&gt;
&lt;li&gt;Matt B taking Jeremy's headstock directly to the forehead.&lt;/li&gt;
&lt;li&gt;Jeremy trying to punch his guitar through the ceiling of the foundry at the '05 BOB&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Choice Quotes&lt;/h3&gt;

&lt;p&gt;“I'm highly offended you don't like our music” — Jeremy, ‘Live at Zebedees 2005’&lt;/p&gt;

&lt;p&gt;“What, did you guys come here to play pool?” — Jeremy, a few moments later.&lt;/p&gt;

&lt;p&gt;“Our sound has evolved somewhat” — Jeremy, as the band arrived to play at CPIT's ‘mellow lunchtime’ series, for which they had submitted Disarm's “Captain's Calling” as their demo.&lt;/p&gt;

&lt;p&gt;“Can you ask Brehaut if I can borrow the Mesa/Sovtek/his guitar tonight?” — Jeremy, every week.&lt;/p&gt;

&lt;p&gt;“It's already in the car.” — Matt, in response, every week.&lt;/p&gt;

&lt;p&gt;“Gotta keep the cannons cool” — Tony, in reference to Matt and his consumption of jugs of water.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/rR8fa-qOrjM" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/YXpv9MykFAA" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/EAmHNkdx_MI" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/gZ0n1Iop_xM" height="1" width="1"/&gt;</description><pubDate>Mon, 13 Sep 2010 11:38:01 +1200</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/misc/tragedy-of-the-commons/</guid><feedburner:origLink>http://gregbrown.co.nz/misc/tragedy-of-the-commons/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/rR8fa-qOrjM/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/YXpv9MykFAA/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/EAmHNkdx_MI/</feedburner:origLink></item><item><title>Fantastic Contraptions</title><link>http://feedproxy.google.com/~r/gregbrown/~3/-8G1HoQ3EbU/</link><description>&lt;p&gt;&lt;em&gt;This article originally appeared on &lt;a href="http://brehaut.net"&gt;brehaut.net&lt;/a&gt; – thanks to Andrew for providing the content.&lt;/em&gt;  &lt;/p&gt;

&lt;h3&gt;Post your clever and amusing Fantastic Contraptions here&lt;/h3&gt;

&lt;p&gt;(For the uninitiated: &lt;a href="http://fantasticcontraption.com"&gt;Fantastic Contraption&lt;/a&gt; )&lt;/p&gt;

&lt;p&gt;– Greg&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=938718"&gt;A Trebuchet!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=973552"&gt;Multi-crane&lt;/a&gt; (Probably more complicated than necessary...)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=976763"&gt;Dangler&lt;/a&gt; (This took freaking ages)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1022872"&gt;A (somewhat overkilled) catapult&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1075777"&gt;Heave!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1162479"&gt;No barrier!&lt;/a&gt; (design originally – mattw's)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok here's a challenge: lets see who can make the most powerful catapult, on the "Wall" level. Here's mine: &lt;a href="http://FantasticContraption.com/?designId=1025420"&gt;A too-powerful catapult&lt;/a&gt;. Feel free to tweak it or start from scratch. &amp;mdash; – Greg&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1026021"&gt;Mission accomplished&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;– mattw&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://fantasticcontraption.com/?designId=979412"&gt;A Trebupult!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=979651"&gt;A Backhoe&lt;/a&gt; (the two-piece idea shamelessly stolen)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=983960"&gt;Tuppeny Farthing/Hamster Wheel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I quite like &lt;a href="http://FantasticContraption.com/?designId=1073080"&gt;this guy&lt;/a&gt;. I'm not sure why; maybe just because he seems such a battler. Pretty robust, too.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1073865"&gt;Because the easy way is too easy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;– brehaut&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=983465"&gt;An Arm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=982795"&gt;Overcomplicated wheel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=983226"&gt;Bridge Building machine&lt;/a&gt; Idea also stolen shamelessly &lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=983248"&gt;Simple Pivot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=983876"&gt;Jumper!&lt;/a&gt; Better than the movie of the same name&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=984672"&gt;Tracker Trailer assembly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1080662"&gt;handling vehicle&lt;/a&gt; This took ages to get a solution for, but i'm really happy with how it turned out.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1081722"&gt;Climber!&lt;/a&gt; Finally got the climber balanced properly&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1081887"&gt;Grappler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1082207"&gt;Another chained cart thing&lt;/a&gt; I need to bust out more&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1309166"&gt;A really simple junkyard solution&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;– Steven&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1106151"&gt;An elevator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1105864"&gt;A caterpillar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;– Stephen&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1314177"&gt;A tank&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1315953"&gt;A burrowing machine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;– Nato
On 'the wall', I decided I wanted to drive over it without breaking down the wall (or using a catapult). So I did &lt;a href="http://FantasticContraption.com/?designId=2514647"&gt;this&lt;/a&gt;
But really, the game is too easy with wheels. I like doing it without them, for example:
&lt;a href="http://fantasticcontraption.com/?designId=2515711"&gt;A clever catapult&lt;/a&gt;
&lt;a href="http://FantasticContraption.com/?designId=2508552"&gt;A more basic catapult&lt;/a&gt;
&lt;a href="http://FantasticContraption.com/?designId=2520868"&gt;My no sticks solution to '4 balls'&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Found Contraptions&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://FantasticContraption.com/?designId=1116361"&gt;Back and Forth&lt;/a&gt; With only five pieces
(That has to be the most elegant contraption I've seen yet. &amp;mdash; – greg)
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://fantasticcontraption.com/?designId=1158547"&gt;Conveyor&lt;/a&gt; Found by – Angus&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/7_pRuOFWtig" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/EbiavDgLdo4" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/z3bE6Vd7JgA" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/-8G1HoQ3EbU" height="1" width="1"/&gt;</description><pubDate>Mon, 13 Sep 2010 11:27:27 +1200</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/misc/fantastic-contraptions/</guid><feedburner:origLink>http://gregbrown.co.nz/misc/fantastic-contraptions/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/7_pRuOFWtig/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/EbiavDgLdo4/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/z3bE6Vd7JgA/</feedburner:origLink></item><item><title>Music Gear</title><link>http://feedproxy.google.com/~r/gregbrown/~3/D-WtM20j7qI/</link><description>&lt;h4&gt;Guitars&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Diplomat Tele&lt;/strong&gt; — an old school MIJ tele copy- has a jazz-style humbucker at the bridge and has been retro-fitted with a seymour duncan hotrails at the neck. No longer has a dodgy nut, after Canterbury Music spent a month fiddling with it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profile Strat&lt;/strong&gt; — another old japanese gat that plays really nicely. Recently treated to a set of Kinman AVN Blues noiseless single coil pickups- sounding good although still very bright- I'm thinking the guitar itself is just a very bright guitar, regardless of the pickups.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ovation S778&lt;/strong&gt; — roundback, adamas top acoustic guitar – plugged-in tone is as good as you'll find for a piezo, and not too bad acoustic either.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ibanez TV Series 12 String&lt;/strong&gt; — An old school solid top 12 string guitar- sounds mint, but neck needs some work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Diplomat Hollowbody Electric&lt;/strong&gt; — Bigsby trem, dual single coils,  &lt;em&gt;very&lt;/em&gt; old school. Sounds pretty good but needs a re-fret- however I'm reluctant to spend $300 fixing up a guitar that only cost me $40. Makes a nice collector's piece anyway.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Baby Taylor&lt;/strong&gt; — 3/4 scale solid top acoustic- sounds a lot better than you think it will... and fits in your carry-on luggage.  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Effects&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Korg Tuner&lt;/strong&gt; — Self explanatory really- also functions as an impedance buffer betweeen guitar and low impedance effects:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vox V847 Wah&lt;/strong&gt; — The quintessential vintage wah...&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Voodoo Lab Microvibe&lt;/strong&gt; — Univibe (of Hendrix fame) clone&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boss SD-1&lt;/strong&gt; — Standard boss overdrive&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EHX Memory Man&lt;/strong&gt; — Bucket-brigade, modulated goodness... when it works :(&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Diamond Memory Lane&lt;/strong&gt; — More modulated bucket-brigade tonal bling- this one works reliably and also has tap tempo! &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Voodoo Lab Sparkle Drive&lt;/strong&gt; — Ibanez TS-808 (vintage overdrive) clone, plus a blendable clean boost&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ibanez DML delay&lt;/strong&gt; — Great sounding and versatile modulation delay- one pedal which I'm glad has 6 knobs as it lets you get anything from a shimmering chorus to edge-style dotted quaver delay to spacey echos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ibanez PT-9&lt;/strong&gt; — Old school analog phaser&lt;/li&gt;
&lt;li&gt;Several other boxes in various operational states...&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Amplifiers&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Matchless Spitfire&lt;/strong&gt; — a 15w, all tube, EL84 powered, tube rectified tone machine &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Acoustic Image Clarus&lt;/strong&gt; — ultra-light 200w acoustic instrument amp, paired with an Ampeg 1x10 cab&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Recording&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Alesis iO|14&lt;/strong&gt; — Firewire recording console with 4 mic pres&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audio Technica AT3035&lt;/strong&gt; — Studio condenser mic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shure Beta57&lt;/strong&gt; — great vocal mic, tends to pick up a lot of highs when used to mic an amp- good for clean but not so much for dirty&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Behringer B1&lt;/strong&gt; — condenser mic, could be used for studio recording but perhaps better suited to the role of studio doorstop&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AKG k240&lt;/strong&gt; — Monitoring headphones&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Other gear&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Alto mixing desk&lt;/strong&gt; — 16 channel, pretty cheap but does the job&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DI boxes&lt;/strong&gt; — one Behringer, one Alto&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cables&lt;/strong&gt; — mostly homemade, with neutrik connectors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Piece of wood&lt;/strong&gt; — with velcro, to which pedals are stuck&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Wishlist&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Peavey Wolfgang Archtop&lt;/strong&gt; — basically, this thing out Les-Pauls every Les Paul I have ever played&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fender Strat&lt;/strong&gt; — like, a proper one- L-Series perhaps...&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fender Blackface Deluxe Reverb&lt;/strong&gt; — for use with the above&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Roland Space Echo&lt;/strong&gt; — tape delay&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1913 Gibson Mandolin&lt;/strong&gt; — As played recently at Emerald Music, Seattle - only $2k!&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/bJQUv4FVW04" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/Xsy0PpDy1_s" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/UL1a9RDVxm0" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/D-WtM20j7qI" height="1" width="1"/&gt;</description><pubDate>Mon, 13 Sep 2010 11:21:28 +1200</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/misc/music-gear/</guid><feedburner:origLink>http://gregbrown.co.nz/misc/music-gear/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/bJQUv4FVW04/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/Xsy0PpDy1_s/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/UL1a9RDVxm0/</feedburner:origLink></item><item><title>Lacto-Fermented Ginger beer</title><link>http://feedproxy.google.com/~r/gregbrown/~3/NxvhE1dj1jo/</link><description>&lt;p&gt;&lt;em&gt;This article originally appeared on &lt;a href="http://brehaut.net"&gt;brehaut.net&lt;/a&gt; – thanks to Andrew for providing the content.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pretty much all plants have lactobacilli living on or in them, but they get killed off by bleaching and pesticides used in industrial agriculture. These bugs have been used to make yoghurt, sourdough, sauerkraut, kimchi, relishes and various other traditional foods for hundreds (thousands?) of years, and apparently are highly beneficial, but they are the enemy of the food industry as they make things too unpredictable, and — being alive — cannot be left in storage for months. Hence we have pasteurisation and "preservatives" to kill them off.  &lt;/p&gt;

&lt;p&gt;That and the fact that 95% of commercial ginger beer is gross inspired me to have a crack at it myself, and having finally had some success, I thought I'd share my experiences... &lt;/p&gt;

&lt;h2&gt;Making a Culture&lt;/h2&gt;

&lt;p&gt;To make a culture I bought some organic sultanas and soaked 1/4 a cup of them in around 300ml of water in a loosely covered jar for a week. Then I strained the sultanas and added approximately 1 tablespoon of white sugar and 1 tablespoon of chopped ginger root to the water --- Give the chooks the sultanas. After a few days it started to bubble, indicating success!&lt;/p&gt;

&lt;p&gt;Leaving the jar uncovered exposes it to mould etc, covering it tightly doesn't let the gas escape.&lt;/p&gt;

&lt;h3&gt;Observations&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Although I despise white sugar, brown seems to give noxious results when used to make a culture... so white it has to be. (although I haven't tried raw sugar which might be fine)&lt;/li&gt;
&lt;li&gt;Boiled water seems to work much better than straight from the tap - my theories are a) boiling removes suspended oxygen from the water, which gives the anaerobic lactobacilli a head start over noxious aerobes (ie mould) and/or b) my tap water contains some sort of noxious bugs that mess with the culture and which are killed off by boiling the water (obviously it needs to be cooled off before use to avoid pasteurising the culture itself into oblivion)&lt;/li&gt;
&lt;li&gt;Not sure why the sultanas worked where other plants failed (I tried a mandarin and organic white tea leaves), it may have been other factors.&lt;/li&gt;
&lt;li&gt;The fruit must be organic; the bleaches and pesticides used on non-organic produce tend to wipe out the cultures.&lt;/li&gt;
&lt;li&gt;Use pure water, chlorination and/or fluoridation of water supplies seems to also kill of the cultures. Neither of these boil off apparently. &lt;a href="http://brehaut.net"&gt;Brehaut&lt;/a&gt; thinks this is a key problem with his attempts at culture. &lt;a href="/"&gt;Greg&lt;/a&gt; thanks his lucky stars for tap water pumped straight out of the Hurunui river.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://brehaut.net"&gt;Brehaut&lt;/a&gt; Likes to mash the ginger under the knife before chopping to get more surface area accessible to the culture.&lt;/li&gt;
&lt;li&gt;It's worth paying attention to the amount of sugar you feed the culture daily; If there is too much in the jar it may start to preserve the solution rather than feed the bug. Too little and it just goes dormant.
&lt;ul&gt;
&lt;li&gt;I'm not sure about this, I make elderflower cordial (which obviously has a high sugar content) and it tends to go fizzy pretty quickly. Admittedly it's wild yeast and not lactobacilli that are causing it. &lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Ginger beer&lt;/h2&gt;

&lt;p&gt;To make the ginger beer I boiled up some ginger root and lemon and a cup of raw sugar, then cooled it off, 3/4 filled two lemonade bottles and topped up with culture. Then leave it in the sun for a week and voila, delicious ginger beer!&lt;/p&gt;

&lt;p&gt;I topped up the culture with boiled water, added sugar and now it's bubbling away waiting for the next batch...&lt;/p&gt;

&lt;h3&gt;Questions&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How much of your culture do you add to the bottles, and do you top up the bug in any fashion?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Again I don't really know but here's a rough recipe for 1.5L: 1 thumb-size piece of ginger, 1 lemon, 200gm sugar&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does anyone have any ideas as to how we could establish what's actually growing in the culture? Maybe not to the point of identifying the species; personally I'm interested to know if there's any yeast in there or is it just bacilli.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/XdYikQyUWcc" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/DAbYCZ5ZQRQ" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/Xq7hycKDEYE" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/NxvhE1dj1jo" height="1" width="1"/&gt;</description><pubDate>Mon, 13 Sep 2010 11:12:09 +1200</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/misc/ginger-beer/</guid><feedburner:origLink>http://gregbrown.co.nz/misc/ginger-beer/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/XdYikQyUWcc/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/DAbYCZ5ZQRQ/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/Xq7hycKDEYE/</feedburner:origLink></item><item><title>Miscellany </title><link>http://feedproxy.google.com/~r/gregbrown/~3/NtdnwxqkZUc/</link><description>&lt;p&gt;Miscellaneous odds and ends, mostly prunings from &lt;a href="http://brehaut.net"&gt;brehaut.net&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/cpjxTuQ7M5E" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/juBmt53-Wto" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/vz6qPs1R_Go" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/NtdnwxqkZUc" height="1" width="1"/&gt;</description><pubDate>Mon, 13 Sep 2010 11:10:57 +1200</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/misc/</guid><feedburner:origLink>http://gregbrown.co.nz/misc/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/cpjxTuQ7M5E/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/juBmt53-Wto/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/vz6qPs1R_Go/</feedburner:origLink></item><item><title>How to restore proportional window resizing in Snow Lepoard's Expose</title><link>http://feedproxy.google.com/~r/gregbrown/~3/RnxsD5nkfTE/</link><description>&lt;p&gt;For heavy Expose users, Snow Leopard's expose is utterly worthless due to the unintuitive grid layout, which Apple &lt;a href="http://www.apple.com/macosx/refinements/"&gt;considers a feature.&lt;/a&gt; This hack restores OSX Leopard's proportional resizing and positioning of items when Expose is invoked, and means I can once again identify Expose windows without squinting at the screen!  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Copied wholesale from &lt;a href="http://forums.macrumors.com/showthread.php?p=9333493#post9333493"&gt;this macrumours thread&lt;/a&gt; - thanks to user &lt;a href="http://forums.macrumors.com/member.php?u=171449"&gt;miknos&lt;/a&gt; for putting it together.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Instructions&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download the fixed Dock.app &lt;a href="http://gregbrown.co.nz/media/uploads/FixedDock.zip"&gt;here&lt;/a&gt;. Extract to Desktop.&lt;/li&gt;
&lt;li&gt;Create a new folder in desktop called OldDock.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open terminal and (changing username) type:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo chown -R root /Users/USER/Desktop/Dock.app
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;type your password if necessary&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo chgrp -R wheel /Users/USER/Desktop/Dock.app
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now copy/paste everything. Don't forget to change to your username:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo killall Dock &amp;amp;&amp;amp; \
sudo mv /System/Library/CoreServices/Dock.app /Users/USER/Desktop/OldDock/ &amp;amp;&amp;amp; \
sudo mv /Users/USER/Desktop/Dock.app /System/Library/CoreServices/
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;Restart and Enjoy!&lt;/h4&gt;

&lt;p&gt;To revert, just put the dock.app inside OldDock folder in Desktop and repeat everything.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/qxM5IFzhm4o" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/c9T6P2B1kWM" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/yztEb5v8cBI" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/RnxsD5nkfTE" height="1" width="1"/&gt;</description><pubDate>Mon, 16 Aug 2010 15:37:49 +1200</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/misc/fix-snow-leopard-expose/</guid><feedburner:origLink>http://gregbrown.co.nz/misc/fix-snow-leopard-expose/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/qxM5IFzhm4o/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/c9T6P2B1kWM/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/yztEb5v8cBI/</feedburner:origLink></item><item><title>Django Google Analytics Template Tag</title><link>http://feedproxy.google.com/~r/gregbrown/~3/uYxdqEC26YM/</link><description>&lt;h2&gt;&lt;code&gt;google_analytics_tags.py&lt;/code&gt;&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;from django import template
import os, sys, re


dirname = os.path.dirname(globals()["__file__"])
register = template.Library()
domain_check = re.compile("(?:localhost|127\\.0\\.0\\.1):\\d{4}")


def ga_tracker(request, id, track_staff=False):
    if ((not request.user.is_staff) or track_staff) and not domain_check.match(request.get_host()):
        return "&amp;lt;script type=\"text/javascript\"&amp;gt;var gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");document.write(unescape(\"%%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%%3E%%3C/script%%3E\"));&amp;lt;/script&amp;gt;" % id
    else:
        return ""

register.simple_tag(ga_tracker)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Usage&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;{% ga_tracker request "UA-XXXXXXX-XX" %}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;or, to track staff members as well as regular visitors&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{% ga_tracker request "UA-XXXXXXX-XX"  1 %}
&lt;/code&gt;&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/UlWyYjW7PXM" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/zyKSeZfXuO4" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/VXDENwSaJuQ" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/uYxdqEC26YM" height="1" width="1"/&gt;</description><pubDate>Wed, 24 Feb 2010 13:42:52 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/django-google-analytics-template-tag/</guid><feedburner:origLink>http://gregbrown.co.nz/code/django-google-analytics-template-tag/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/UlWyYjW7PXM/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/zyKSeZfXuO4/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/VXDENwSaJuQ/</feedburner:origLink></item><item><title>Home</title><link>http://feedproxy.google.com/~r/gregbrown/~3/sxWFp-cdrJU/</link><description>&lt;p&gt;Welcome. This site is the online home of web developer, skillet enthusiast &amp;amp; surf junkie Greg Brown. &lt;/p&gt;

&lt;h2&gt;&lt;a href="/development/"&gt;Development&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;I build websites for a living - if you need one, drop me a line at greg@gregbrown.co.nz. I'm also available for hire as a contract PHP or Python programmer. See the &lt;a href="/development/"&gt;web development&lt;/a&gt; section for more information.&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://cheapflightnotifier.gregbrown.co.nz/"&gt;Cheap Flight Notifier&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;This site makes it easier to avoid missing out on great flight deals from a &lt;a href="/media/uploads/dropbox/airnz.png"&gt;litigious&lt;/a&gt; local airline. &lt;a href="http://cheapflightnotifier.gregbrown.co.nz/"&gt;Sign up and try it out for yourself!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a href="/code/"&gt;Code&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Various code snippets and mini-projects musings reside here. Check out my &lt;a href="/code/djangocms2000/"&gt;django cms&lt;/a&gt; if you're that way inclined.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/Nv1EfkF2IZg" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/iIinNFsnpRw" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/9hE3H3UC9ao" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/sxWFp-cdrJU" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/</guid><feedburner:origLink>http://gregbrown.co.nz/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/Nv1EfkF2IZg/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/iIinNFsnpRw/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/9hE3H3UC9ao/</feedburner:origLink></item><item><title>Links</title><link>http://feedproxy.google.com/~r/gregbrown/~3/2Ev5iOyPkgY/</link><description>&lt;p&gt;&lt;em&gt;Sites I endorse or frequent&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Interests&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://worldsweetworld.com/"&gt;World Sweet World Magazine&lt;/a&gt; — Crafty DIY goodness&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.greens.org.nz/"&gt;The Green Party blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://slowfood.com/"&gt;Slow Food International&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ranprieur.com"&gt;Ran Prieur&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Friends&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://kibblewhitestreet.blogspot.com/"&gt;Kibblewhite Street&lt;/a&gt; – Jess (my wonderful wife) has an infrequently-updated blog&lt;/li&gt;
&lt;li&gt;&lt;a href="http://brehaut.net/"&gt;Andrew Brehaut's wiki&lt;/a&gt; (I'm an occasional contributor)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://problemattic.net/"&gt;Matt Wilson's blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fraser Dron's &lt;a href="http://fraserdron.com/"&gt;blog&lt;/a&gt; &amp;amp; &lt;a href="http://cavalcadesmusic.com/"&gt;musical project, Cavalcades&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Misc&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://musselinn.co.nz/"&gt;The Mussel Inn&lt;/a&gt; — Quite simply the best eatery in the world, period.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://addingtoncoffee.org.nz"&gt;Addington Coffee Co-Op&lt;/a&gt; — Christchurch's coolest cafe and an excellent roastery&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/HG6qs-Kh4aY" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/wFKqDlwx0Bc" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/N61iWJiAIgA" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/2Ev5iOyPkgY" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/links/</guid><feedburner:origLink>http://gregbrown.co.nz/links/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/HG6qs-Kh4aY/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/wFKqDlwx0Bc/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/N61iWJiAIgA/</feedburner:origLink></item><item><title>Website Development (Django, Javascript, Python)</title><link>http://feedproxy.google.com/~r/gregbrown/~3/caxtuIP7nnk/</link><description>&lt;p&gt;I'm available for hire for contract web programming — you can email me at &lt;a href="&amp;#109;&amp;#97;i&amp;#x6c;&amp;#116;&amp;#111;&amp;#x3a;&amp;#103;&amp;#114;&amp;#101;&amp;#103;&amp;#x40;&amp;#x67;&amp;#114;&amp;#101;&amp;#x67;&amp;#98;&amp;#x72;&amp;#x6f;&amp;#x77;&amp;#x6e;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#x2e;&amp;#x6e;z"&gt;&amp;#103;&amp;#114;&amp;#101;&amp;#103;&amp;#x40;&amp;#x67;&amp;#114;&amp;#101;&amp;#x67;&amp;#98;&amp;#x72;&amp;#x6f;&amp;#x77;&amp;#x6e;&amp;#x2e;&amp;#99;&amp;#x6f;&amp;#x2e;&amp;#x6e;z&lt;/a&gt; or call me on +64276310883 to discuss.&lt;/p&gt;

&lt;p&gt;You can view some examples of my work on &lt;a href="http://github.com/gregplaysguitar/"&gt;Github&lt;/a&gt;; and I also have a profile on &lt;a href="http://djangopeople.net/gregb/"&gt;Django people&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My specialty is fast, usable web applications and database-driven websites. I have 5+ years experience building everything from a pallet tracking system for produce exporters, to a high-traffic corporate events guide website, to a large-scale enterprise content management system currently in use on over 100 sites.&lt;/p&gt;

&lt;h2&gt;Technical Details&lt;/h2&gt;

&lt;p&gt;I started out working with PHP, MySQL on the server side, along with Javascript, HTML, CSS, DOM and AJAX, but in 2008 I moved to Django/Python for my server-side code and it's now my platform of choice. I maintain my own &lt;a href="http://www.openhost.co.nz/ref/6629"&gt;Openhost VPS&lt;/a&gt; running Ubuntu Linux, with Apache 2.2, Python 2.5, Django 1.0, PHP 5 and MySQL 5 — I can host sites on there or with your hosting company of choice, so long as they provide the relevant technologies. If you're of a technical bent, check out some of the &lt;a href="/code/"&gt;code I've released into the wild.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm also a keen student in the fields of web standards and usability. I don't do graphic design, but I can work with your graphic designer, or recommend one to suit your project.&lt;/p&gt;

&lt;p&gt;The following is a sample of my past work.&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://greyareaproductions.com"&gt;Grey Area Productions&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Gallery/portfolio site for a Christchurch-based photographer and filmmaker. &lt;br /&gt;
&lt;a href="http://greyareaproductions.com"&gt;greyareaproductions.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://durhamhealth.co.nz"&gt;Durham Health&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Durhamhealth.co.nz is an informational site built for a new medical practice in Rangiora, North Canterbury. Content is maintained by the client via a custom CMS system. &lt;br /&gt;
&lt;a href="http://durhamhealth.co.nz"&gt;durhamhealth.co.nz&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://glentui.co.nz"&gt;Glentui Meadows&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Another informational site, with custom CMS, built for a lodge and conference centre in North Canterbury. &lt;br /&gt;
&lt;a href="http://glentui.co.nz"&gt;glentui.co.nz&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://nakedmanuka.co.nz"&gt;Naked Manuka&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Hand-crafted manuka outdoor furniture made in Canterbury - site was built for a local handyman, in exchange for the construction of a raised floor in our office. &lt;br /&gt;
&lt;a href="http://nakedmanuka.co.nz"&gt;nakedmanuka.co.nz&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://kiwikitchens.co.nz"&gt;Kiwi Kitchens&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;A local kitchen design and manufacture firm. &lt;br /&gt;
&lt;a href="http://kiwikitchens.co.nz"&gt;kiwikitchens.co.nz&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;&lt;a href="http://cheapflightnotifier.gregbrown.co.nz"&gt;Cheap Flight Notifier&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Built because I was sick of missing out on &lt;a href="http://grabaseat.co.nz"&gt;cheap&lt;/a&gt; flights, this site emails daily flight deals based on your preferences. Goals were a simple interface, reliability and Doing One Thing Well. I haven't put any particular effort into promoting it but it's growing steadily. &lt;br /&gt;
&lt;a href="http://cheapflightnotifier.gregbrown.co.nz"&gt;cheapflightnotifier.gregbrown.co.nz&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/uLwKAhtfE0g" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/g8jJVt7q42o" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/Jmqx0UrX6yY" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/caxtuIP7nnk" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/development/</guid><feedburner:origLink>http://gregbrown.co.nz/development/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/uLwKAhtfE0g/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/g8jJVt7q42o/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/Jmqx0UrX6yY/</feedburner:origLink></item><item><title>Djangocms2000 Reference</title><link>http://feedproxy.google.com/~r/gregbrown/~3/T8cnWXwaYgk/</link><description>&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/gHvv3qGuFpI" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/rgNnuL7woK0" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/Ea6yghXo_5M" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/T8cnWXwaYgk" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/djangocms2000/reference/</guid><feedburner:origLink>http://gregbrown.co.nz/code/djangocms2000/reference/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/gHvv3qGuFpI/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/rgNnuL7woK0/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/Ea6yghXo_5M/</feedburner:origLink></item><item><title>Djangocms2000 - A Flexible Django CMS</title><link>http://feedproxy.google.com/~r/gregbrown/~3/HE9kDVwpoFo/</link><description>&lt;p&gt;Designed to be a a drop-in replacement for django's built in &lt;a href="http://docs.djangoproject.com/en/dev/ref/contrib/flatpages/"&gt;Flatpages&lt;/a&gt; app, this is the tool I use for most static content on my django sites (including this one).&lt;/p&gt;

&lt;p&gt;Having been involved in a large-scale cms project in the past, I know only too well how such systems can bloat to the point where they actually get in the developer's way rather than helping. I've also found that clients don't actually use the cms that much - as the developer, I tend to end up doing most of the maintenance myself, as well as the initial site setup. With that in mind, my goals for this system were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be easy enough for people with no html knowledge to use&lt;/li&gt;
&lt;li&gt;But, must be something I'd use myself, by choice, to set up a website instead of just using html (ie when there is no cms requirement)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As well as utilising the built-in django admin, I've created an edit-in-place feature which allows simple one-click editing of content, when an administrator is logged in. I'm planning to get a demo of this up some time soon. The edit-in-place code utilises &lt;a href="http://jquery.com/"&gt;jquery&lt;/a&gt; and should work without too much tweaking required. Here's a screenshot of &lt;a href="/media/uploads/dropbox/editing-example.png"&gt;the editor in action&lt;/a&gt; on this very page.&lt;/p&gt;

&lt;p&gt;Get it at &lt;a href="http://github.com/gregplaysguitar/djangocms2000/"&gt;http://github.com/gregplaysguitar/djangocms2000/&lt;/a&gt;, or check out the &lt;a href="/code/djangocms2000/reference/"&gt;reference&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/yIHWOK5tCoA" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/ANWihRzrL64" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/xBJon-ajXKk" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/HE9kDVwpoFo" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/djangocms2000/</guid><feedburner:origLink>http://gregbrown.co.nz/code/djangocms2000/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/yIHWOK5tCoA/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/ANWihRzrL64/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/xBJon-ajXKk/</feedburner:origLink></item><item><title>Code - Javascript, Django etc</title><link>http://feedproxy.google.com/~r/gregbrown/~3/A_rD4rrsag4/</link><description>&lt;p&gt;A repository for anything I feel might be useful to someone... feel free to contact me with any feedback at  &lt;a href="&amp;#x6d;&amp;#97;&amp;#x69;&amp;#x6c;&amp;#116;&amp;#x6f;&amp;#58;&amp;#103;&amp;#x72;&amp;#101;&amp;#103;&amp;#64;&amp;#103;&amp;#114;&amp;#101;&amp;#x67;b&amp;#x72;&amp;#111;&amp;#x77;&amp;#x6e;&amp;#46;&amp;#99;&amp;#x6f;&amp;#46;&amp;#110;&amp;#x7a;"&gt;&amp;#103;&amp;#x72;&amp;#101;&amp;#103;&amp;#64;&amp;#103;&amp;#114;&amp;#101;&amp;#x67;b&amp;#x72;&amp;#111;&amp;#x77;&amp;#x6e;&amp;#46;&amp;#99;&amp;#x6f;&amp;#46;&amp;#110;&amp;#x7a;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/hdbBsG9Q304" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/K_W7Buy7cIM" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/NyRT7J0v5RQ" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/A_rD4rrsag4" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/</guid><feedburner:origLink>http://gregbrown.co.nz/code/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/hdbBsG9Q304/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/K_W7Buy7cIM/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/NyRT7J0v5RQ/</feedburner:origLink></item><item><title>A Django Captcha without Freetype or the Python Imaging Library (PIL)</title><link>http://feedproxy.google.com/~r/gregbrown/~3/YdfPb8Kcz8o/</link><description>&lt;blockquote&gt;
  &lt;p&gt;If, like me, you've had trouble installing the &lt;a href="http://www.pythonware.com/products/pil/"&gt;Python Imaging Library&lt;/a&gt; or &lt;a href="http://freetype.sourceforge.org"&gt;FreeType&lt;/a&gt;, you may have also had trouble getting a captcha to work. Here's my quick and dirty workaround — be warned, this is &lt;em&gt;very&lt;/em&gt; low level security, and shouldn't be used on high-profile sites.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;Form Field&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;from django.forms.fields import CharField, MultiValueField
from django.forms.widgets import TextInput, MultiWidget, HiddenInput
from django import forms
from django.utils.safestring import mark_safe
import hashlib
import random


class CaptchaTextInput(MultiWidget):
    def __init__(self,attrs=None):
        widgets = (
            HiddenInput(attrs),
            TextInput(attrs),
        )
        super(CaptchaTextInput,self).__init__(widgets,attrs)

    def decompress(self,value):
        if value:
            return value.split(',')
        return [None,None]


    def render(self, name, value, attrs=None):
        ints = (random.randint(0,9),random.randint(0,9),)
        answer = hashlib.sha1(str(sum(ints))).hexdigest()

        extra = "What is %d + %d?" % (ints[0], ints[1])
        value = [answer, u'',]

        return mark_safe(extra + super(CaptchaTextInput, self).render(name, value, attrs=attrs))


class CaptchaField(MultiValueField):
    widget=CaptchaTextInput

    def __init__(self, *args,**kwargs):
        fields = (
            CharField(show_hidden_initial=True), 
            CharField(),
        )
        super(CaptchaField,self).__init__(fields=fields, *args, **kwargs)

    def compress(self,data_list):
        if data_list:
            return ','.join(data_list)
        return None


    def clean(self, value):
        super(CaptchaField, self).clean(value)
        response, value[1] = value[1].strip().lower(), ''

        if not hashlib.sha1(str(response)).hexdigest() == value[0]:
            raise forms.ValidationError("Sorry, you got the security question wrong - to prove you're not a spammer, please try again.")
        return value
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Usage&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;from django import forms
from models import Post
from ABOVE-FILE import CaptchaField

class CaptchaTestForm(forms.Form):
    myfield = AnyOtherField()
    ...
    security_check = CaptchaField()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Credit to the author of &lt;a href="http://code.google.com/p/django-simple-captcha/"&gt;django-simple-captcha&lt;/a&gt;, from whom I borrowed most of this code.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/bw8lFxnQVMo" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/-x6_93O6rhk" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/QOEfGm3hTVk" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/YdfPb8Kcz8o" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/django-captcha-without-freetype-or-pil/</guid><feedburner:origLink>http://gregbrown.co.nz/code/django-captcha-without-freetype-or-pil/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/bw8lFxnQVMo/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/-x6_93O6rhk/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/QOEfGm3hTVk/</feedburner:origLink></item><item><title>Optimising Django, Apache and mod_wsgi for a lightweight Ubuntu VPS</title><link>http://feedproxy.google.com/~r/gregbrown/~3/HjVH722ieBU/</link><description>&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; I'm now using an &lt;a href="http://nginx.org/"&gt;nginx&lt;/a&gt;-based solution on my server - I serve all my static content via nginx, proxying to apache (using the worker mgm and mod-wsgi) for django requests, and a fastcgi daemon for php. I've experienced a huge increase in efficiency over serving everything via apache. The below is still relevant but I would recommend reading up on &lt;a href="http://wiki.nginx.org/NginxConfiguration"&gt;nginx configuration&lt;/a&gt; before worrying about what I've written here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE 2:&lt;/strong&gt; One thing I neglected to mention is mod_wsgi 2.0's inactivity-timeout parameter, which makes a huge difference if you're hosting lots of low traffic django sites - see &lt;a href="http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives"&gt;the mod_wsgi docs.&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;   &lt;/p&gt;

&lt;p&gt;Recently I've been playing around with a very lightweight (128MB RAM) Ubuntu VPS from &lt;a href="http://openhost.co.nz/"&gt;Openhost&lt;/a&gt;. I had been running a few low-traffic PHP sites on there, but recently I've started using &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt; so I installed Apache's &lt;a href="http://code.google.com/p/modwsgi/"&gt;mod_wsgi&lt;/a&gt; to serve my django sites. This lead to some memory issues — here's what I did to overcome them.&lt;/p&gt;

&lt;h2&gt;My server setup:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu Server 8.04, on a 128MB VPS&lt;/li&gt;
&lt;li&gt;Package management via apt&lt;/li&gt;
&lt;li&gt;Apache 2.2&lt;/li&gt;
&lt;li&gt;Python 2.5&lt;/li&gt;
&lt;li&gt;Django 1.0&lt;/li&gt;
&lt;li&gt;Sqlite3&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;mod_wsgi VirtualHost configuration&lt;/h2&gt;

&lt;p&gt;After installing and enabling mod_wsgi, I added the following to each site's VirtualHost directive:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;VirtualHost&amp;gt;
    ...
    WSGIScriptAlias / /path-to-site/apache/django.wsgi
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This simply embeds the django instance into the existing apache processes, resulting in them growing to upwards of 30MB over time. Luckily, mod_wsgi can be run in "daemon mode", which means the django instance gets its own apache listener, and the standard apache listeners can focus just on serving static media. To enable daemon mode, I changed my VirtualHost as follows:&lt;/p&gt;

&lt;p&gt;Even with the &lt;em&gt;threads&lt;/em&gt; and &lt;em&gt;processes&lt;/em&gt; options set to 1, each of the 4 daemons (one per site) was using around 20MB - still not a sustainable level on a 128MB VPS. Next step was to try consolidating the sites into one daemon. This has the advantage that it only loads the various python libraries etc into memory once, rather than for every site. To achieve this, I added the following to my http.conf:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;WSGIDaemonProcess django-shared processes=1 threads=1 display-name=%{GROUP}
WSGIProcessGroup django-shared
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and set all my VirtualHosts to use this group, ie:&lt;/p&gt;

&lt;p&gt;This resulted in one mod_wsgi daemon using around 32MB of ram, and so far is the best I've managed.&lt;/p&gt;

&lt;h2&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;For low-traffic sites, the fact that django is a long-running process is not really an advantage as it means the process will be using memory even if the site hasn't had a hit in days. However, the benefits of using django far outweigh the downsides for me.&lt;/p&gt;

&lt;p&gt;I'd recommend playing around with the different config options — obviously for larger sites there will be advantages to having a daemon for each site. I'm yet to experience a traffic spike so I'm not sure how my configuration will perform under pressure.&lt;/p&gt;

&lt;p&gt;It's worth looking into how you can optimise other processes on your server too. For me the biggest waste of memory was mysql (used on my php sites). Following &lt;a href="http://chrisjohnston.org/2008/configuring-a-lightweight-apache-mysql-install-on-debian-ubuntu"&gt;Chris Johnston's guide&lt;/a&gt; I was able to reduce this dramatically, freeing up more memory for my webservers.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/8FSv32HaVsk" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/mLpIkawlT1s" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/1F4qoFBCKVk" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/HjVH722ieBU" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/optimising-django-apache-and-mod_wsgi-for-a-lightweight-ubuntu-vps/</guid><feedburner:origLink>http://gregbrown.co.nz/code/optimising-django-apache-and-mod_wsgi-for-a-lightweight-ubuntu-vps/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/8FSv32HaVsk/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/mLpIkawlT1s/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/1F4qoFBCKVk/</feedburner:origLink></item><item><title>Image morpher (Jquery plugin)</title><link>http://feedproxy.google.com/~r/gregbrown/~3/h6h8E4pqTZk/</link><description>&lt;p&gt;This plugin is used to morph from one image to another. It relies on jquery 1.3 (I haven't tried it on older versions). Usage is as simple as $('img').morph('/images/newimage.jg')  &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/*

usage:

$('img').morphImage('/path/to/image.jpg', newWidth, newHeight, callback);

*/
$.fn.imageMorph = (function(src, width, height, callback, SPEED){
    var SPEED = SPEED || 300;


    return this.each(function(){

        var img = $(this),
            newImg = $('&amp;lt;img&amp;gt;'),
            throbber = img.parent().find('.throbber');


        if (img.hasClass('morpher')) {
            img.remove();
            return;
        }

        if (!throbber.length) {
            throbber = $('&amp;lt;span class="throbber"&amp;gt;&amp;lt;/span&amp;gt;');
            img.parent().append(throbber);
            throbber.hide();
        }


        var throbberTimeout = setTimeout(function() {
            // if the image is cached, it will load instantly, so we don't want the throbber
            // flickering on and off in that case
            throbber.show();
        }, 60);

        newImg.css({
            position: 'absolute',
            top: 0,
            left: 0,
            width: img.width()+'px',
            height: img.height()+'px',
            opacity: 0,
            cursor: 'pointer'
        }).addClass('morpher');
        img.parent().append(newImg).css({
            width: img.width()+'px',
            height: img.height()+'px'
        });


        newImg.load(function() {

            var css = {width:width+'px', height:height+'px', opacity:1};
            img.parent().stop().animate(css, SPEED);
            img.stop().animate(css, SPEED);
            clearTimeout(throbberTimeout);
            throbber.hide();
            newImg.animate(css, SPEED, function() {
                img.remove();
                newImg.removeClass('morpher');
                (callback || function(){})();
            });
        });

        newImg.attr('src', src);
    });
});
&lt;/code&gt;&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/ixp3iYlNpoA" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/hBSjFIGrGbI" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/QO8AJAsHbtc" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/h6h8E4pqTZk" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/image-morpher-jquery-plugin/</guid><feedburner:origLink>http://gregbrown.co.nz/code/image-morpher-jquery-plugin/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/ixp3iYlNpoA/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/hBSjFIGrGbI/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/QO8AJAsHbtc/</feedburner:origLink></item><item><title>Github Flavoured Markdown - Python Implementation</title><link>http://feedproxy.google.com/~r/gregbrown/~3/Jq6HyOGMPgA/</link><description>&lt;p&gt;Having searched without success for a python version of Github's &lt;a href="http://github.github.com/github-flavored-markdown/"&gt;Github Flavored Markdown,&lt;/a&gt; – designed to make &lt;a href="http://daringfireball.net/projects/markdown/"&gt;markdown&lt;/a&gt; more intuitive for users not familiar with the syntax – I decided to write one myself.&lt;/p&gt;

&lt;p&gt;This is basically a direct python port of github's Ruby code, except that I dislike lambdas. :)&lt;/p&gt;

&lt;p&gt;See &lt;a href="http://github.github.com/github-flavored-markdown/"&gt;http://github.github.com/github-flavored-markdown/&lt;/a&gt; for more details.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;"""
Github flavoured markdown - ported from
http://github.github.com/github-flavored-markdown/

Usage:

    html_text = markdown(gfm(markdown_text))

(ie, this filter should be run on the markdown-formatted string BEFORE the markdown
filter itself.)

"""

import re
try: 
   from hashlib import md5 as md5_func
except ImportError:
   from md5 import new as md5_func

def gfm(text):


    # Extract pre blocks
    extractions = {}
    def pre_extraction_callback(matchobj):
        hash = md5_func(matchobj.group(0)).hexdigest()
        extractions[hash] = matchobj.group(0)
        return "{gfm-extraction-%s}" % hash
    pre_extraction_regex = re.compile(r'{gfm-extraction-338ad5080d68c18b4dbaf41f5e3e3e08}', re.MULTILINE | re.DOTALL)
    text = re.sub(pre_extraction_regex, pre_extraction_callback, text)


    # prevent foo_bar_baz from ending up with an italic word in the middle
    def italic_callback(matchobj):
        if len(re.sub(r'[^_]', '', matchobj.group(1))) &amp;gt; 1:
            return matchobj.group(1).replace('_', '\_')
        else:
            return matchobj.group(1)
    text = re.sub(r'(^(?! {4}|\t)\w+_\w+_\w[\w_]*)', italic_callback, text)


    # in very clear cases, let newlines become &amp;lt;br /&amp;gt; tags
    def newline_callback(matchobj):
        if len(matchobj.group(1)) == 1:
            return matchobj.group(0).rstrip() + '  \n'
        else:
            return matchobj.group(0)
    text = re.sub(r'^[\w\&amp;lt;][^\n]*(\n+)', newline_callback, text)


    # Insert pre block extractions
    def pre_insert_callback(matchobj):
        return extractions[matchobj.group(1)]
    text = re.sub(r'{gfm-extraction-([0-9a-f]{40})\}', pre_insert_callback, text)

    return text
&lt;/code&gt;&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/QBalzBAsjmQ" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/552wED8Acck" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/NqYMAo_Y_7I" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/Jq6HyOGMPgA" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/githib-flavoured-markdown-python-implementation/</guid><feedburner:origLink>http://gregbrown.co.nz/code/githib-flavoured-markdown-python-implementation/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/QBalzBAsjmQ/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/552wED8Acck/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/NqYMAo_Y_7I/</feedburner:origLink></item><item><title>Speed up Django with far-future expires, compression and other best practices</title><link>http://feedproxy.google.com/~r/gregbrown/~3/bt8e8iK1rg0/</link><description>&lt;p&gt;As a web developer with a shoddy rural internet connection, I'm always interested in speeding up my sites. One technique for doing this is &lt;em&gt;far-future expires&lt;/em&gt; — i.e. telling the browser to cache media requests forever, then changing the uri when the media changes. In this article, I outline how to implement this and several other techniques in django.  &lt;/p&gt;

&lt;h2&gt;Goals&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Reduce http requests for css and js files to a bare minimum.&lt;/li&gt;
&lt;li&gt;Add far-future-expires headers to all static content&lt;/li&gt;
&lt;li&gt;Gzip all css and js content&lt;/li&gt;
&lt;li&gt;Reduce css/js filesize by minification&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;The django-compress App&lt;/h2&gt;

&lt;p&gt;First up, I installed the &lt;a href="http://code.google.com/p/django-compress/"&gt;django-compress&lt;/a&gt; app. I was about to build my own solution when I realised this one did exactly what I needed — gotta love the django community. Configuring is straightforward — the &lt;a href="http://code.google.com/p/django-compress/wiki"&gt;project wiki&lt;/a&gt; has articles on &lt;a href="http://code.google.com/p/django-compress/wiki/Installation"&gt;installation,&lt;/a&gt; &lt;a href="http://code.google.com/p/django-compress/wiki/Configuration"&gt;configuration,&lt;/a&gt; and &lt;a href="http://code.google.com/p/django-compress/wiki/Usage"&gt;usage.&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I copied the compress/ directory into my django/library/ folder (which is on the python path) and added "compress" to my INSTALLED_APPS.&lt;/p&gt;

&lt;h2&gt;Apache Configuration&lt;/h2&gt;

&lt;p&gt;Once I had django-compress up and running, I had achieved goal #1. To achieve #2 and #3 I needed to configure apache to send the right headers along with each request. To do this, I put the following directive in my httpd.conf file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;DirectoryMatch /path-to-django-projects/([^/]+)/media&amp;gt;

    Order allow,deny
    Allow from all

    # Insert mod_deflate filter
    SetOutputFilter DEFLATE
    # Netscape 4.x has some problems...
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    # Netscape 4.06-4.08 have some more problems
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    # MSIE masquerades as Netscape, but it is fine
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
    # Don't compress images
    SetEnvIfNoCase Request_URI \
    \.(?:gif|jpe?g|png)$ no-gzip dont-vary
    # Make sure proxies don't deliver the wrong content
    Header append Vary User-Agent env=!dont-vary

    # MOD EXPIRES SETUP
    ExpiresActive on
    ExpiresByType text/javascript "access plus 10 year"
    ExpiresByType application/x-javascript "access plus 10 year"
    ExpiresByType text/css "access plus 10 years"
    ExpiresByType image/png  "access plus 10 years"
    ExpiresByType image/x-png  "access plus 10 years"
    ExpiresByType image/gif  "access plus 10 years"
    ExpiresByType image/jpeg  "access plus 10 years"
    ExpiresByType image/pjpeg  "access plus 10 years"
    ExpiresByType application/x-flash-swf  "access plus 10 years"
    ExpiresByType application/x-shockwave-flash  "access plus 10 years"

    # No etags as we're using far-future expires
    FileETag none

&amp;lt;/DirectoryMatch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Notes&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&amp;lt;DirectoryMatch /path-to-django-projects/([^/]+)/media&amp;gt; is equivalent to writing &amp;lt;Directory /path-to-django-projects/site-name/media&amp;gt; for each site.&lt;/li&gt;
&lt;li&gt;mod_deflate configuration directives from the &lt;a href="http://httpd.apache.org/docs/2.2/mod/mod_deflate.html"&gt;Apache site.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Note that I'm sending far-future-expires headers for images and flash too — at this stage, that means I have to manually change the filenames whenever I change the content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that for all my django sites' media directories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;static content (except images) is gzipped via mod_deflate&lt;/li&gt;
&lt;li&gt;everything gets a header telling the browser to cache it for 10 years&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note you will need mod_deflate and mod_expires enabled in your apache config - if you have apache 2.2 it should just be a matter of copying the relevant files from apache2/mods-available/ to /apache2/mods-enabled/.&lt;/p&gt;

&lt;h2&gt;Minification&lt;/h2&gt;

&lt;p&gt;Step #4 was the trickiest of the lot, and many would argue that it's not really worth the trouble. Depending on how verbosely you comment your js and css, it may or may not be worthwhile for you — personally, I just thought I may as well go the whole hog. In the end, I probably only saved a few percent worth of bandwidth for my small content sites, but it'll be more significant with js-heavy web-apps.&lt;/p&gt;

&lt;p&gt;For js minification, django-compress comes with jsmin built in. I've found this to be ideal for the job, and it is enabled by default.&lt;/p&gt;

&lt;p&gt;For CSS, django-compress comes with &lt;a href="http://csstidy.sourceforge.net/"&gt;CSSTidy&lt;/a&gt; — a CSS parser and optimiser — built in, in the form of csstidy_python. (You can also use a csstidy binary if you have one installed.) Personally, I find CSSTidy messes with my css, and more significantly, messes with that of my css framework of choice, &lt;a href="http://960.gs"&gt;960.gs.&lt;/a&gt; I was after something that simply stripped whitespace, newlines and comments, without parsing the code. 
After scouring the web, I came across &lt;a href="http://www.issuetrackerproduct.com/Documentation#slimmer"&gt;Slimmer&lt;/a&gt; — a lightweight pyhon app that did exactly what I needed. After installing it, I added the following file to the django-compress app's filters directory.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#compress/filters/slimmer_css/__init__.py

import slimmer
from compress.filter_base import FilterBase

class SlimmerCSSFilter(FilterBase):
    def filter_css(self, css):
        return slimmer.css_slimmer(css)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then it was simply a matter of adding the following line to my settings.py file, as per the django-compress documentation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;COMPRESS_CSS_FILTERS = ('compress.filters.slimmer_css.SlimmerCSSFilter',)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So my complete django-compress configuration in settings.py was as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# compress app settings
COMPRESS_CSS = {
    'all': {
        'source_filenames': (
            'css/lib/reset.css',
            'css/lib/text.css',
            'css/lib/960.css',
            'css/style.css',
        ),
        'output_filename': 'compress/c-?.css',
        'extra_context': {
            'media': 'screen,projection',
        },
    },

    # other CSS groups goes here
}
COMPRESS_JS = {
    'all': {
        'source_filenames': ('js/lib/jquery.js', 'js/behaviour.js',),
        'output_filename': 'compress/j-?.js',
    },
}

COMPRESS = True
COMPRESS_VERSION = True
COMPRESS_CSS_FILTERS = ('compress.filters.slimmer_css.SlimmerCSSFilter',)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Other best practices&lt;/h2&gt;

&lt;p&gt;I keep all my css within the &amp;lt;head&amp;gt; tags, and js at the bottom of the page — this is because the web browser needs to download all the css before it can start rendering the page, but doesn't need the js. It doesn't actually speed up the site, but it gives the impression of loading faster, and the user is unlikely to click on anything before the js has loaded anyway.&lt;/p&gt;

&lt;p&gt;For a definitive guide, see &lt;a href="http://developer.yahoo.com/performance/rules.html"&gt;Yahoo's performance rules&lt;/a&gt;. I also recommend Yahoo's &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow,&lt;/a&gt; and if you are one of the 3 remaining web developers without it, &lt;a href="http://getfirebug.com/"&gt;Firebug.&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/h10ryeIImnU" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/BRzZsmhYZWA" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/1yTK7DUCTf0" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/bt8e8iK1rg0" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/speed-up-django-with-far-future-expires-compression-and-other-best-practices/</guid><feedburner:origLink>http://gregbrown.co.nz/code/speed-up-django-with-far-future-expires-compression-and-other-best-practices/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/h10ryeIImnU/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/BRzZsmhYZWA/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/1yTK7DUCTf0/</feedburner:origLink></item><item><title>Colophon</title><link>http://feedproxy.google.com/~r/gregbrown/~3/_ZJ9e03rL9o/</link><description>&lt;p&gt;This site was built using &lt;a href="http://djangoproject.org"&gt;django&lt;/a&gt;, &lt;a href="http://www.python.org/"&gt;python&lt;/a&gt;, &lt;a href="http://jquery.com/"&gt;jquery&lt;/a&gt;, and the usual html/css/js.&lt;/p&gt;

&lt;p&gt;Css grid by &lt;a href="http://960.gs"&gt;960.gs&lt;/a&gt; (not that I'm exactly using it to its potential) and flash-free font replacement by &lt;a href="http://cufon.shoqolate.com/generate/"&gt;cufon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Content is maintained via my own &lt;a href="/code/djangocms2000/"&gt;djangocms2000&lt;/a&gt;. Source code is version controlled via &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt;. &lt;code&gt;rev=canonical&lt;/code&gt;
support by &lt;a href="http://github.com/jacobian/django-shorturls"&gt;shorturls.&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/_G8vPPdgSwM" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/iPa-A87P7eM" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/qNDIpVZdq14" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/_ZJ9e03rL9o" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/colophon/</guid><feedburner:origLink>http://gregbrown.co.nz/colophon/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/_G8vPPdgSwM/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/iPa-A87P7eM/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/qNDIpVZdq14/</feedburner:origLink></item><item><title>Django Simple Search</title><link>http://feedproxy.google.com/~r/gregbrown/~3/2kaH_DvScdI/</link><description>&lt;p&gt;This django form class creates a search form for a model and generates a query from the submitted data.&lt;/p&gt;

&lt;p&gt;To use, extend the BaseSearchForm class, defining a Meta class with the following
values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;base_qs&lt;/code&gt; is the queryset to search, ie. &lt;code&gt;MyModel.objects&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;search_fields&lt;/code&gt; are the fields to search, using the same syntax as the django admin 
directive of the same name, ie.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;'fieldname'&lt;/code&gt; - field must contain the search string&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'^fieldname'&lt;/code&gt; - field must start with the search string&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'=fieldname'&lt;/code&gt; - field must exactly equal the search string&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'@fieldname'&lt;/code&gt; - performs a fulltext search (mysql/postgres only) on field&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Related model fields can also be searched, ie &lt;code&gt;'mycategory__name'&lt;/code&gt; will search
the name field on the mycategory model.&lt;/p&gt;

&lt;p&gt;Custom fields can also be added to filter the results - by default, these perform
an exact-match search on the model field of the same name. A &lt;code&gt;prepare_FIELDNAME&lt;/code&gt;
method can be defined for each custom field for advanced queries - this method
should return a Q instance for addition to the overall query.&lt;/p&gt;

&lt;h2&gt;Example form class (myapp/forms.py)&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;from simple_search import BaseSearchForm
from myapp.models import MyModel, MyCategory
from django.db.models import Q


class MyModelSearchForm(BaseSearchForm):
    class Meta:
        base_qs = MyModel.objects
        search_fields = ['^name','description',] 

    """ 
    A custom addition - the absence of a prepare_category method means
    the query will search for an exact match on this field.
    """
    category = forms.ModelChoiceField(
        queryset = MyCategory.live.all(),
        required = False
    )

    """ 
    This field creates a custom query addition via the prepare_start_date
    method.
    """
    start_date = forms.DateField(
        required = False,
        input_formats = ('%Y-%m-%d',),
    )
    def prepare_start_date(self):
        if self.cleaned_data['start_date']:
            return Q(creation_date__gte=self.cleaned_data['start_date'])
        else:
            return ""
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Example use in a view (myapp/views.py)&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;from django.shortcuts import render_to_response
from django.template import RequestContext
from myapp.forms import MyModelSearchForm

def search(request):

    if request.GET:
        form = MyModelSearchForm(request.GET)
        if form.is_valid():
            results = form.get_result_queryset()
        else:
            results = []
    else:
        form = MyModelSearchForm()
        results = []


    return render_to_response(
        'search.html',
        RequestContext(request, {
            'form': form,
            'results': results,
        })
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Demo&lt;/h2&gt;

&lt;p&gt;You can try it out on this site, either from the search box in the footer or &lt;a href="/search/"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Get the code&lt;/h2&gt;

&lt;p&gt;You can &lt;a href="http://gist.github.com/gists/291442/download"&gt;download&lt;/a&gt; or &lt;a href="http://gist.github.com/291442"&gt;view&lt;/a&gt; the code on github.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/Uq2lINpePUs" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/7JgfSD1Bsn8" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/l5lEDR8tms0" height="1" width="1"/&gt;&lt;img src="http://feeds.feedburner.com/~r/gregbrown/~4/2kaH_DvScdI" height="1" width="1"/&gt;</description><pubDate>Mon, 01 Feb 2010 03:14:05 +1300</pubDate><guid isPermaLink="false">http://gregbrown.co.nz/code/django-simple-search/</guid><feedburner:origLink>http://gregbrown.co.nz/code/django-simple-search/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/Uq2lINpePUs/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/7JgfSD1Bsn8/</feedburner:origLink><feedburner:origLink>http://feedproxy.google.com/~r/gregbrown/~3/l5lEDR8tms0/</feedburner:origLink></item></channel></rss>
