<?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>@TheKeyboard &#187; blog experiment</title>
	<atom:link href="http://www.littlehart.net/atthekeyboard/tag/blog-experiment/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.littlehart.net/atthekeyboard</link>
	<description>Facebook should&#039;ve be written in unicornSchemaLang, because everyone *knows* that PHP is no good for anything, right?</description>
	<lastBuildDate>Thu, 29 Jul 2010 20:05:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>So It Ends, Gentle Reader</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/30/so-it-ends-gentle-reader/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/30/so-it-ends-gentle-reader/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 20:17:12 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=623</guid>
		<description><![CDATA[Thanks so much for sticking with me during my November blogging experiment. By my reckoning, I only missed one week-day blog post (it was on a Friday, and I posted something on a Saturday to make up for it. I will not be keeping up with that pace in the month of December, but I [...]]]></description>
			<content:encoded><![CDATA[<p>
Thanks so much for sticking with me during my November blogging experiment.  By my reckoning, I only missed one week-day blog post (it was on a Friday, and I posted something on a Saturday to make up for it.  I will not be keeping up with that pace in the month of December, but I do expect to cover some more interesting topics.
</p>
<p>
I have contemplated making December &#8220;blog reader month&#8221; where I do some blog posts on topics suggested by my readers.  Feel free to make requests in the comments, email them to me (if you can figure out my email address), or send &#8216;em to me via Twitter.  I promise full attribution.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/30/so-it-ends-gentle-reader/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Better Application Deployment</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/27/better-application-deployment/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/27/better-application-deployment/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 00:24:09 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=621</guid>
		<description><![CDATA[I&#8217;ve been working on the open source web service that we make available to our clients, trying to get some caching into the application to improve performance. It got me to thinking: what would be the best way to get our clients to install this application. By best way, I do not mean easiest way. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on the <a href="http://www.sportsdb.org/sd/sportscaster">open source web service</a> that we make available to our clients, trying to get some caching into the application to improve performance.  It got me to thinking:  what would be the best way to get our clients to install this application.
</p>
<p>
By best way, I do not mean easiest way.  The easiest way is to say &#8220;here&#8217;s the tarball, extract it and install it in place&#8221;.  That&#8217;s currently the method we use for distribution.  I must admit that I have been negligent in updating recent builds on the site.  The real solution here is to create an automated build system that I can use to package up newer versions of the code and put them up on the web site.
</p>
<p>
Others have suggested that I should examine the use of Pear as a way to distribute this PHP application.  That&#8217;s fine, but the next time they update it would overwrite any changes they made to things like display templates.  So I guess the current method is the best&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/27/better-application-deployment/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>What&#8217;s In Chris&#8217; Brain &#8211; Blog Experiment Version</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/26/whats-in-chris-brain-blog-experiment-version/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/26/whats-in-chris-brain-blog-experiment-version/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 04:29:24 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>
		<category><![CDATA[Cassandra]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[exist]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Postgres]]></category>
		<category><![CDATA[Twisted]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=618</guid>
		<description><![CDATA[I had a few drinks last night with my fellow Milton-area PHP developer and we got to talking about a lot of different topics. I will summarize a few of them here: Concurrency is still drawing significant interest from me I recommended my friend check out Tim Bray&#8217;s Concur.next series (yes, I know I&#8217;m whipping [...]]]></description>
			<content:encoded><![CDATA[<p>
I had a few drinks last night with my fellow <a href="http://www.hutchic.com">Milton-area PHP developer</a> and we got to talking about a lot of different topics.  I will summarize a few of them here:
</p>
<p><h3><em>Concurrency is still drawing significant interest from me</em></h3>
</p>
<p>I recommended my friend check out Tim Bray&#8217;s <a href="http://www.tbray.org/ongoing/When/200x/2009/09/27/Concur-dot-next">Concur.next</a> series (yes, I know I&#8217;m whipping this topic like a dead hors).  We discussed how when you&#8217;ve done so much work in the stateless environment of the web, made slightly more state-full by hacks like sessions and Ajax, how hard it is to wrap your mind around the idea of concurrency and event-driven models of programming.  Much like Mr. Bray I believe that somewhere out there is what will become the popular toolkit for creating concurrent programs, both on the server and on web sites.</p>
<h3><em>What about data stores when coupled with concurrent code</em></h3>
<p>Say I were to create a stripped-down version of the XML-feed reading program that we sell at work.  Say I write it in, oh, Twisted Python and then have the documents it grabbed get tossed into the XML data store I&#8217;m using at work.  I imagine that I would grab my list of files to retrieve and then spin off a thread/agent/worker/whatever to grab each one, do the necessary processing and then insert that document into the database.</p>
<p>
So, I guess it comes down to the ability of the datastore itself to handle concurrent requests?  I mean, if I was talking to a RDBMS like MySQL or Postgresql, can I count on them to handle concurrent inserts or updates?  That is a question worth doing some research about.
</p>
<h3><em>There is an opportunity to become a domain expert in the NoSQL field</em></h3>
<p>
If you were a freelancer who wants to live on the cutting edge, I would seriously invest time in learning one of <a href="http://couchdb.apache.org/">CouchDB</a> / <a href="http://incubator.apache.org/cassandra/">Cassandra</a> / <a href="http://www.mongodb.org/display/DOCS/Home">MongoDB</a> and figure out scenarios where these can be used.  Next step?  Profit!!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/26/whats-in-chris-brain-blog-experiment-version/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Useful Tools For Non-Designers</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/25/useful-tools-for-non-designers/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/25/useful-tools-for-non-designers/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 00:50:40 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>
		<category><![CDATA[Blueprint CSS]]></category>
		<category><![CDATA[Boks]]></category>
		<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=615</guid>
		<description><![CDATA[I&#8217;ve been playing with Blueprint CSS until such time that I can create grid layouts in CSS myself. My friend Kevin pointed out an Air app called Boks that lets you create your own layouts, complete with inserting HTML along with it too. The screencasts are awesome and I highly recommend it to hard-core programmers [...]]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;ve been playing with <a href="http://www.blueprintcss.org/">Blueprint CSS</a> until such time that I can create grid layouts in CSS myself.  My friend <a href="http://twitter.com/chiggsy">Kevin</a> pointed out an Air app called <a href="http://toki-woki.net/p/Boks/">Boks</a> that lets you create your own layouts, complete with inserting HTML along with it too.  The screencasts are awesome and I highly recommend it to hard-core programmers who need some help with layouts.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/25/useful-tools-for-non-designers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Definition of Open Source</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/24/the-definition-of-open-source/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/24/the-definition-of-open-source/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 01:49:31 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>
		<category><![CDATA[GPL]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=612</guid>
		<description><![CDATA[This has been bugging me all day long You have a project that is licensed under the GPL and that project is a front-end to act as a web service that speaks to a database that is populated by a proprietary product and you are the biggest user of this open source project is it [...]]]></description>
			<content:encoded><![CDATA[<p>
This has been bugging me all day long</p>
<ul>
<li>You have a project that is licensed under the GPL</li>
<li>and that project is a front-end to act as a web service</li>
<li>that speaks to a database that is populated</li>
<li>by a proprietary product</li>
<li>and you are the biggest user of this open source project</li>
<li>is it really open source?
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/24/the-definition-of-open-source/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>What Thrashed Around In Chris&#8217; Brain This Past Weekend</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/23/what-thrashed-around-in-chris-brain-this-past-weekend/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/23/what-thrashed-around-in-chris-brain-this-past-weekend/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 02:12:49 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=606</guid>
		<description><![CDATA[(The blog experiment continues: 1 post every weekday in November and I think I only skipped one, but made up for it with a Saturday post) Node.js is something I want to use, but I do not know what for For those who don&#8217;t know, Node is a &#8220;toolkit for writing extremely high performance non-blocking [...]]]></description>
			<content:encoded><![CDATA[<p>(The blog experiment continues: 1 post every weekday in November and I think I only skipped one, but made up for it with a Saturday post)</p>
<p>
<i>Node.js is something I want to use, but I do not know what for</i><br />
For those who don&#8217;t know, <a href="http://nodejs.org/">Node</a> is a &#8220;toolkit for writing extremely high performance non-blocking event driven network servers in JavaScript&#8221;.  In other words, it&#8217;s for writing server-side Javascript with an emphasis on providing concurrency.  Damn you Tim Bray, I cannot avoid seeing concurrency everywhere since you started your <a href="http://www.tbray.org/ongoing/When/200x/2009/09/27/Concur-dot-next">Concur.next</a> series on your blog.  It fascinates me, and I don&#8217;t even do any kind of work where I need to worry about concurrency.  Not yet anyway.
</p>
<p>
Simon Wilson (someone I follow from the Django community) has a great article explaining why <a href="http://simonwillison.net/2009/Nov/23/node/">Node.js is genuinely exciting</a> to him, and my old CakePHP landsmann Felix shows <a href="http://debuggable.com/posts/streaming-file-uploads-with-node-js:4ac094b2-b6c8-4a7f-bd07-28accbdd56cb">how to handling streaming file uploads in node.js</a>.  Like so many new technologies, Node.js starts out as a solution looking for a problem but as I become more familiar with concurrency it all becomes a little clearer.
</p>
<p>
<i>While <a href='http://www.vim/org">Vim</a> is awesome, don&#8217;t put up with any crap from it</i><br />
I had been experiencing a problem with Vim.  Well, two problems.  The first big one was weird behaviour involving the <a href="http://www.vim.org/scripts/script.php?script_id=1849">AutoClose</a> plugin.  It would spit out brackets and quotes at the weirdest time, and I found myself doing a lot of unnecessary keystrokes (and toggling in and out of insert mode) to get things done.  So I deleted it.  Enough of that crap.  Same goes with my attempts to use the <a href="http://www.vim.org/scripts/script.php?script_id=69">Project plugin</a>.  I just could not get it to work properly.  DELETED.
</p>
<p>
Vim&#8217;s ability to be ultracustomizable ALSO makes it easy to dump stuff when you no longer what to use it.  Heck, I even see some stuff in my .vimrc that I am not using any more.  Mappings I did to accomplish some specific tasks.  Those were deleted too.
</p>
<p>
<i>Understanding the concept of callbacks opens your mind to all sorts of possibilities</i><br />
While callbacks are related to my use of Javascript (jQuery uses them to great success) I also find myself digging into the <a href="http://docs.djangoproject.com/en/dev/topics/signals/">documentation in Django on signals</a>, which are callbacks by another name:  functionality that is executed when certain events happen.</p>
<p>Django uses them all over the place, and CakePHP uses them as well.  When I look at the CodeIgniter code that powers <a href="http://www.sportso.com">Sportso</a>, I often ruminate about what programming techniques or design patterns could help me reduce the amount of code that has actually been written.  CodeIgniter doesn&#8217;t really support callbacks except in the form of allowing you to define custom functions for validation purposes.  It&#8217;s a start I get.  I wonder what the code would look like if I could define more code that is triggered when specific events happen?  Any time I find myself typing the same block of code over and over again, it is only natural that I seek to reduce how often I need to do it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/23/what-thrashed-around-in-chris-brain-this-past-weekend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cleaning Up The Dev Environment</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/20/cleaning-up-the-dev-environment/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/20/cleaning-up-the-dev-environment/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 03:15:19 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Postgres]]></category>
		<category><![CDATA[Zend Server Community Edition]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=604</guid>
		<description><![CDATA[Once I got a production push out of the way at work, I set about recreating my PHP development environment. Currently I was running PHP 5.3.0 with Apache2 and Postgresql 8.4, all installed via MacPorts. Why the time for a change? Two reasons. The first one is my desire to constantly tinker and tweak my [...]]]></description>
			<content:encoded><![CDATA[<p>Once I got a production push out of the way at work, I set about recreating my PHP development environment.  Currently I was running PHP 5.3.0 with Apache2 and Postgresql 8.4, all installed via MacPorts.  Why the time for a change?  Two reasons.  The first one is my desire to constantly tinker and tweak my environment.  The second reason was to test out some things for future work projects.
</p>
<p>
Those who follow the blog know that I had successfully convinced The Powers That Be at work to use Zend Framework to build out future PHP projects.  I also decided that it would be good to examine if <a href='http://www.zend.com/en/products/server-ce/index'>Zend Server Community Issue</a> is a viable stack for us.  In order to make that decision, I needed to install it and check it out.</p>
<p>
Being the cutting-edge guy that I am, I installed the beta version that comes with PHP 5.3.  I remember that I was having problems getting ZSCE working on Snow Leopard, but those problems seem to have disappeared.  Flawless install, and with about 10 minutes of work tweaking Apache configuration files I had my new PHP stack back.
</p>
<p>
I have to admit that to a jaded &#8220;I am sick of personally compiling my stack&#8221; person that I am acting like these days, the control panel for Zend Server is nice.  Point and click to add whatever extensions I need.  No more recompiling!  Perfect.  After playing with this, next week I will be installing it on our dev server at work.  MySQL is totally busticated for some reason, so wiping things clean and starting over with the Zend-provided version will be a welcome thing.  It will allow me to actually test some things front-to-back on the dev server.  Apathy towards your program&#8217;s environment is a killer, so this will help me tighten things up.
</p>
<p>
So, with that out of the way the next step was figuring out what to do about Postgres.  Luckily this part was *really* easy.  I did a pg_dump of the entire database server and went and installed the version of Postgresql for OS-X that <a href="http://www.enterprisedb.com/products/download.do">EnterpriseDB</a> has.  Again, a flawless install and I was up and running in no time.  Created my desired users, and imported my database.  Again, it took about 10 minutes.
</p>
<p>
Other than the required tweak to my php.ini to declare the timezone for the server (I got this humungous warning in CodeIgniter about it) it was smooth sailing.  So now I had Apache 2, PHP 5.3, MySQL and Postgresql, all detached from MacPorts.  Next step was to remove MacPorts itself and I was good to go.
</p>
<p>
MacPorts, it was fun, but I&#8217;ve learned to get by without you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/20/cleaning-up-the-dev-environment/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Programming Environment of the Future</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/19/the-programming-environment-of-the-future/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/19/the-programming-environment-of-the-future/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 01:12:50 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>
		<category><![CDATA[Google Chrome]]></category>
		<category><![CDATA[Mozilla Bespin]]></category>
		<category><![CDATA[phpMyAdmin]]></category>
		<category><![CDATA[phpPgAdmin]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=602</guid>
		<description><![CDATA[While working away I was listening (okay, and peeking once in a while) at the live stream from the announcement from Google about Chrome OS, an operating system they&#8217;ve been working on. From what I can tell, it&#8217;s going to be some stripped-down version of Linux with a window manager that runs one thing: the [...]]]></description>
			<content:encoded><![CDATA[<p>While working away I was listening (okay, and peeking once in a while) at the live stream from the announcement from Google about <a href="http://www.chromium.org/chromium-os">Chrome OS</a>, an operating system they&#8217;ve been working on.  From what I can tell, it&#8217;s going to be some stripped-down version of Linux with a window manager that runs one thing:  the Chrome browser.
</p>
<p>
Now, while I think a netbook is great for someone like my <a href="http://teachersatrisk.com">mom</a>, or my daughter, I cannot imagine myself doing any sort of serious programming work on one.  Or can I?</p>
<p>So, first of all it looks like <a href="http://www.vim.org"> is a non-starter.  That means I would likely have to use something like </a><a href="https://mozillalabs.com/bespin/">Mozilla Bespin</a> as my editor.  A quick Google search showed me that you can edit remote files using Bespin, so that is a good thing.  But I would miss doing all the system-level things I&#8217;ve grown accustomed too.  Would make it pretty much impossible to do command line testing of code.
</p>
<p>
And what about all my tools for managing databases?  All the web-based database manipulation tools (like <a href="http://phpmyadmin.net">phpMyAdmin</a> or <a href="http://phppgadmin.sourceforge.net/">phpPgAdmin</a> can probably meet that need.  But then I&#8217;m looking at some sort of web-based SSH client to be able to look at things like server configurations or slow query logs.  Again, it&#8217;s probably doable but is it optimal?
</p>
<p>
Anyway, it&#8217;s an interesting thought.  Perhaps I should spend some time trying to see if I could actually be productive using the tools I just mentioned above.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/19/the-programming-environment-of-the-future/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using Django As An Admin Area for a PHP Project, Part 1</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/18/using-django-as-an-admin-area-for-a-php-project-part-1/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/18/using-django-as-an-admin-area-for-a-php-project-part-1/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 02:22:58 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[django-admin]]></category>
		<category><![CDATA[Postgres]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=599</guid>
		<description><![CDATA[My work project needed an admin area for doing things like changing the key for a league, or changing the email address for someone's account. You know, typical admin stuff. In the past I had been *gasp* editing SQL by hand via pgAdmin (and my favourite trick of creating an SSH tunnel to the server [...]]]></description>
			<content:encoded><![CDATA[<p>My <a href="http://www.sportso.com">work project</a> needed an admin area for doing things like changing the key for a league, or changing the email address for someone's account.  You know, typical admin stuff.  In the past I had been *gasp* editing SQL by hand via <a href="http://www.pgadmin.org/">pgAdmin</a> (and my favourite trick of creating an SSH tunnel to the server the database is on).  Well, I'd had enough of that.  I also wanted to set things up so when my boss wanted changes done, I could tell him "go do it yourself using this neato-keen admin interface I whipped together".
</p>
<p>
So I got to work creating a <a href="http://www.djangoproject.com">Django</a> project, installed the <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/">django-admin</a> application and got to work.
</p>
<p>
Have I mentioned how I *love* code generation these days?  Can I get "hell yeah!" from the lazy programmers out there?  Django comes with this awesome tool that you access via manage.py called <a href="http://docs.djangoproject.com/en/dev/ref/django-admin/#inspectdb">inspectdb</a>.  What it does is introspect the database you configured for your Django application and generates the output for your models.py file.  However, keep in mind the following:</p>
<ul>
<li>You *will* have to fiddle with the order your classes that represent the models appear in the generated code</li>
<li>You *will* have to go in and alter any field definitions where inspectdb was not able to determine the proper field type and instead guessed.</li>
</ul>
<p>
So, after firing off inspectdb, I then issued a 'python manage.py syncdb' to create all the tables needed for django-admin, created a user for the admin site...and then it got hairy.
</p>
<p>
The documentation for customizing django-admin is good.  And I was able to create just about everything I wanted by actually, you know, READING the documentation.  But I found a problem that I was not able to solve.  I even <a href="http://stackoverflow.com/questions/1758805/problems-with-updating-records-in-django-admin">asked my favourite consultants for help</a> but I could not get it to work the way I *wanted* it to work.  When I told my buddy via IM that it would be easier to whip up this admin in PHP than slog through learning how to do it the Django way, he was not impressed.  He stopped short of saying "you're dead to me now", but I got that vibe.
</p>
<p>
Here's the problem.  I have these two models:</p>
<div class="igBar"><span id="lpython-3"><a href="#" onclick="javascript:showPlainTxt('python-3'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">PYTHON:</span>
<div id="python-3">
<div class="python">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #ff7700;font-weight:bold;">class</span> Permissions<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; league_key = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;color:#800000;">15</span><span style="color: black;">&#41;</span> </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; commissioner_id = models.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span>Accounts, db_column=<span style="color: #483d8b;">'commissioner_id'</span>,</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; to_field=<span style="color: #483d8b;">'id'</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; status = models.<span style="color: black;">IntegerField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; key = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;color:#800000;">50</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; publisher_key = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;color:#800000;">25</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; publisher_display_name = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;color:#800000;">50</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; base_league = models.<span style="color: black;">IntegerField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; share = models.<span style="color: black;">IntegerField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; default_fixture_key = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;color:#800000;">50</span>, blank=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__unicode__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">publisher_key</span> + <span style="color: #483d8b;">' / '</span> + <span style="color: #008000;">self</span>.<span style="color: black;">league_key</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">class</span> Meta:</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; db_table = u<span style="color: #483d8b;">'permissions'</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; verbose_name = <span style="color: #483d8b;">'Permissions'</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; verbose_name_plural = <span style="color: #483d8b;">'Permissions'</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #ff7700;font-weight:bold;">class</span> PermissionsAdmin<span style="color: black;">&#40;</span>admin.<span style="color: black;">ModelAdmin</span><span style="color: black;">&#41;</span>:</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; list_display = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'league_key'</span>, <span style="color: #483d8b;">'publisher_key'</span>, <span style="color: #483d8b;">'commissioner_id'</span>, <span style="color: #483d8b;">'status'</span>,</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">'share'</span>, <span style="color: #483d8b;">'default_fixture_key'</span><span style="color: black;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; list_display_links = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'league_key'</span>,<span style="color: black;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; exclude = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'base_league'</span>,<span style="color: black;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
</p>
<p>
Now, if you look at the definition in there for the base_league field, you will notice that I gave up and called it an IntegerField.  But in reality, it is pointing to another record in the same Permissions table.  We have a concept in Sportso of a "shared league model" where you can base a league on another league and import all sorts of properties and data from it.  I was hoping that I could do something like this:</p>
<div class="igBar"><span id="lpython-4"><a href="#" onclick="javascript:showPlainTxt('python-4'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">PYTHON:</span>
<div id="python-4">
<div class="python">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">base_league = models.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'self'</span>, db_column=<span style="color: #483d8b;">'base_league'</span>, to_field=<span style="color: #483d8b;">'id'</span><span style="color: black;">&#41;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
</p>
<p>
Whenever I did that, I would actually crash Python on my MacBook.  Not a good sign.  If I tried swapping them, I would get an error complaining about violating permissions_pkey, which is the Postgres sequence that was created for the auto-incremented ID for the table.  I did manage to take a look at the SQL it was trying to execute, and it keeps trying to update the 'id' field (which is the primary key) instead of the 'base_league" field.  So I gave up and will continue building out the other parts of the admin.  I just wish I could figure out WHY this self-referencing foreign key setup was not working.
</p>
<p>
If you know what's going on here, let me know via the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/18/using-django-as-an-admin-area-for-a-php-project-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Scary Future World I Will Program In</title>
		<link>http://www.littlehart.net/atthekeyboard/2009/11/12/the-scary-future-world-i-will-program-in/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss</link>
		<comments>http://www.littlehart.net/atthekeyboard/2009/11/12/the-scary-future-world-i-will-program-in/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 04:24:32 +0000</pubDate>
		<dc:creator>Chris Hartjes</dc:creator>
				<category><![CDATA[Chris' Brain]]></category>
		<category><![CDATA[blog experiment]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[Google Go]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Seaside]]></category>
		<category><![CDATA[state]]></category>
		<category><![CDATA[Twisted]]></category>

		<guid isPermaLink="false">http://www.littlehart.net/atthekeyboard/?p=584</guid>
		<description><![CDATA[A lot of the reading I have done on the Internet in the last few years has led me to the following conclusions about the future world I will be programming in: It will require manipulating exponentially more data than now It will require you to understand both parallel processing and concurrency (although to this [...]]]></description>
			<content:encoded><![CDATA[<p>
A lot of the reading I have done on the Internet in the last few years has led me to the following conclusions about the future world I will be programming in:</p>
<ul>
<li>It will require manipulating exponentially more data than now</li>
<li>It will require you to understand both parallel processing and concurrency (although to this simple programmer's brain they appear to be the same thing</li>
<li>A stateless model of the web looks more and more like something that works against human nature</li>
</ul>
<p>
I have become fascinated with languages that talk about dealing with concurrency:  <a href="http://ftp.sunet.se/pub/lang/erlang/index.html">Erlang</a>, Python using <a href="http://twistedmatrix.com">Twisted</a>, <a href="http://clojure.org">Clojure</a>, and the newest kid on the block <a href="http://golang.org/">Google Go</a>.  I have no idea why these interest me so much.  But I find them all fascinating, and I wonder how anything we do at work on the XML-feed-parsing side could benefit from concurrency (and that gets me into the topic of whether or not concurrency matters if you have to write data to a relational database and dealing with locks etc, god I sound like a programming nerd!).
</p>
<p>
Rich Hickey, the creator of Clojure, gave this <a href="http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey">awesome talk</a> about current programming language paradigms and how well suited they are to the highly statefull, concurrent future that I feel we will be facing when building online applications.  Go and watch it and you will find that you knew oh so very little about programming language concepts.
</p>
<p>
So not only are we dealing with concurrency, we also need to deal with state.  PHP is stateless.  "Share-nothing" was a revelation for it's time, and allowed you to build web applications that could horizontally scale quite well.  But then we started requiring state.  So we use things like sessions, and cookies:  tricks that allow us to let data persist between requests.  You could almost throw databases into that category.
</p>
<p>
Perhaps this is ignorant rambling.  All these things make it harder and harder for a statefull environment like the web to act like it is actually retaining values between requests.  Maybe something like <a href="http://en.wikipedia.org/wiki/Seaside_(software)">Seaside</a> is a model to look at it:  it preserves state across requests using continuations, which is a programming concept that you just don't learn when you teach yourself PHP.
</p>
<p>
You could argue that we are on the verge of a major shift in programming language methodologies.  The challenge of programatically handling concurrency and state in a way that programming trolls like me can understand is a huge one.  Tim Bray has been covering this on his blog via his "so fascinating it makes me understands how stupid I really am" <a href="http://www.tbray.org/ongoing/When/200x/2009/09/27/Concur-dot-next">Concur.next</a> series.
</p>
<p>
Will we ever have a statefull, concurrent language for building web apps.  I'm sure we will.  I just don't think it's been written yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.littlehart.net/atthekeyboard/2009/11/12/the-scary-future-world-i-will-program-in/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
