<?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: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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>DeGizmo</title>
	
	<link>http://degizmo.com</link>
	<description>tech, webdev, and etc</description>
	<lastBuildDate>Mon, 26 Apr 2010 12:06:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/degizmo_blog" /><feedburner:info uri="degizmo_blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Simon Willison: Redis Workshop</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/UIOVAoAuRsU/</link>
		<comments>http://degizmo.com/2010/04/26/simon-willison-redis-workshop/#comments</comments>
		<pubDate>Mon, 26 Apr 2010 12:05:51 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Redis]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=35</guid>
		<description><![CDATA[Simon Willison had a great presentation at NoSQL EU recently and published his slides and notes. It&#8217;s quite a comprehensive presentation that&#8217;s a good read for both beginners and advanced users. He presents some great use cases based off of real world examples and utilization.
http://simonwillison.net/2010/Apr/25/redis/

]]></description>
			<content:encoded><![CDATA[<p>Simon Willison had a great presentation at <a href="http://nosqleu.com/">NoSQL EU</a> recently and published his <a href="http://simonwillison.net/static/2010/redis-tutorial/">slides and notes</a>. It&#8217;s quite a comprehensive presentation that&#8217;s a good read for both beginners and advanced users. He presents some great use cases based off of real world examples and utilization.</p>
<p><a href="http://simonwillison.net/2010/Apr/25/redis/">http://simonwillison.net/2010/Apr/25/redis/</a></p>
<p><a href="http://simonwillison.net/static/2010/redis-tutorial/"><img class="alignnone" title="Redis Workshop" src="http://i.imgur.com/NsBHV.jpg" alt="" width="450" height="337" /></a></p>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/UIOVAoAuRsU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/04/26/simon-willison-redis-workshop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/04/26/simon-willison-redis-workshop/</feedburner:origLink></item>
		<item>
		<title>Why you should upstream cache your 404’s</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/5qhS4JlAFdE/</link>
		<comments>http://degizmo.com/2010/03/25/why-you-should-upstream-cache-your-404s/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 18:33:17 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=33</guid>
		<description><![CDATA[There&#8217;s a great reddit thread going with the Onion&#8217;s Tech team on their recent transition to Django and this gem is buried in the conversation
Deep link to post
And the biggest performance boost of all: caching 404s and sending Cache-Control headers to the CDN on 404. Upwards of 66% of our server time is spent on serving 404s [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a great <a href="http://www.reddit.com/r/django/comments/bhvhz/the_onion_uses_django_and_why_it_matters_to_us/">reddit thread</a> going with the Onion&#8217;s Tech team on their recent transition to Django and this gem is buried in the conversation</p>
<p><a href="http://www.reddit.com/r/django/comments/bhvhz/the_onion_uses_django_and_why_it_matters_to_us/c0mvow7">Deep link to post</a></p>
<blockquote><p>And the biggest performance boost of all: caching 404s and sending Cache-Control headers to the CDN on 404. Upwards of 66% of our server time is spent on serving 404s from spiders crawling invalid urls and from urls that exist out in the wild from 6-10 years ago. [Edit: We dropped our outgoing bandwidth by about 66% and our load average on our web server cluster by about 50% after implementing that change]</p></blockquote>
<p>Amazing result for such a simple change. Bang for your buck optimizations are always the best ones.</p>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/5qhS4JlAFdE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/03/25/why-you-should-upstream-cache-your-404s/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/03/25/why-you-should-upstream-cache-your-404s/</feedburner:origLink></item>
		<item>
		<title>Redis’ Virtual Memory Specifications Draft</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/OFO4NyY1338/</link>
		<comments>http://degizmo.com/2010/03/25/redis-virtual-memory-specifications-draft/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 13:00:54 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Redis]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=32</guid>
		<description><![CDATA[Salvatore has posted &#8220;part 1&#8243; of the internals of Redis&#8217; Virtual Memory subsystem today. Below is the intro with the link to full documentation on Google Code below.
This document details the internals of the Redis Virtual Memory subsystem. The intended audience is not the final user but programmers willing to understand or modify the Virtual [...]]]></description>
			<content:encoded><![CDATA[<p>Salvatore has <a href="https://twitter.com/antirez/status/11032342691">posted &#8220;part 1&#8243;</a> of the internals of Redis&#8217; Virtual Memory subsystem today. Below is the intro with the link to full documentation on Google Code below.</p>
<blockquote><p>This document details the internals of the Redis Virtual Memory subsystem. The intended audience is not the final user but programmers willing to understand or modify the Virtual Memory implementation.</p>
<h2>Keys vs Values: what is swapped out?</h2>
<p>The goal of the VM subsystem is to free memory transferring Redis Objects from memory to disk. This is a very generic command, but specifically, Redis transfers only objects associated with values. In order to understand better this concept we&#8217;ll show, using the DEBUG command, how a key holding a value looks from the point of view of the Redis internals.</p></blockquote>
<p><a href="http://code.google.com/p/redis/wiki/VirtualMemorySpecification">Read more</a></p>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/OFO4NyY1338" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/03/25/redis-virtual-memory-specifications-draft/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/03/25/redis-virtual-memory-specifications-draft/</feedburner:origLink></item>
		<item>
		<title>Redis: Relations in a NoSQL world: Using Hashes</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/QRCmXo68qyg/</link>
		<comments>http://degizmo.com/2010/03/24/redis-relations-in-a-nosql-world-using-hashes/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 13:35:45 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Redis]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=30</guid>
		<description><![CDATA[So just yesterday we posted a tutorial on how to use redis to store relational despite relations not being supported. Soon after we published the documentation on the new redis hash type went online. Now hashes by themselves aren&#8217;t exactly relations but, more so an object field store. Extending the same concepts from our first [...]]]></description>
			<content:encoded><![CDATA[<p>So just yesterday we posted a tutorial on how to use redis to<a href="http://degizmo.com/2010/03/23/redis-relations-in-a-nosql-world/"> store relational despite relations not being supported</a>. Soon after we published the <a href="http://code.google.com/p/redis/wiki/Hashes">documentation on the new redis hash type went online</a>. Now hashes by themselves aren&#8217;t exactly relations but, more so an object field store. Extending the same concepts from our first article in namespace utilization and using hashes we can accomplish the same thing in a more formal fashion.</p>
<p>We will repeat the same exercise from the first article, creating a username password store, using hashes.</p>
<p><span id="more-30"></span></p>
<h2>Basic hash overview</h2>
<p>Without going into the technical details we can simplify the concept of redis&#8217;s as a way to store fields in a redis key. In Pythonic terms we can make a redis key into a basic Python <a href="http://docs.python.org/tutorial/datastructures.html#dictionaries">dictionary</a>.</p>
<p>[<strong>key</strong>] : {&#8216;field&#8217; -&gt; &#8216;value&#8217;, &#8216;field&#8217; -&gt; &#8216;value&#8217;, &#8216;field&#8217; -&gt; &#8216;value&#8217;}</p>
<h2>Basic hash usage</h2>
<pre class="brush: python;">
&gt;&gt;&gt; r.hset(&quot;user:adam&quot;, &quot;fullname&quot;, &quot;Adam Smith&quot;)
1
&gt;&gt;&gt; r.hset(&quot;user:adam&quot;, &quot;password&quot;, &quot;thisisapassword&quot;)
1
&gt;&gt;&gt; r.hkeys(&quot;user:adam&quot;)
['fullname', 'password']
&gt;&gt;&gt; r.hvals(&quot;user:adam&quot;)
['Adam Smith', 'thisisapassword']
&gt;&gt;&gt; r.hgetall(&quot;user:adam&quot;)
{'fullname': 'Adam Smith', 'password': 'thisisapassword'}
</pre>
<p>We will break it down line by line here</p>
<ol>
<li>First we are going to make the redis key &#8220;user:adam&#8221; a hash and set the field &#8220;fullname&#8221; in that has to the value &#8220;Adam Smith&#8221; with the redis command hset (Hash Set)</li>
<li>Then we&#8217;ll do the same thing for the field &#8220;password&#8221; and set that field in the hash to it&#8217;s appropriate value.</li>
<li>With the hkeys command we can see all of the keys in the hash set on that redis key</li>
<li>hvals returns all of the values in the redis key</li>
<li>More useful, is the hgetall command. This will return a Python dictionary of all of the fields set in the key</li>
</ol>
<p>As you can see, this is an excellent way to store information about an object without &#8220;faking&#8221; a relation like in our previous tutorial.</p>
<p>As I mentioned in the conclusion of the last article, if we want to change how we store information in redis all we should have to do is to change is change the inner workings of the functions add_user, authenticate_user, delete_user and the rest of our fictitious application should operate without any changes.</p>
<h2>Creating a new user</h2>
<pre class="brush: python;">
r = redis.Redis(&quot;localhost&quot;)
from hashlib import md5

def add_user(username, fullname, password):
    if r.sadd(&quot;users&quot;, username):
        #r.set(&quot;user:%s:fullname&quot; % username, fullname)
        #r.set(&quot;user:%s:password&quot; % username, md5(password).hexdigest() )
        r.hset(&quot;user:%s&quot; % username, &quot;fullname&quot;, fullname)
        r.hset(&quot;user:%s&quot; % username, &quot;password&quot;, md5(password).hexdigest())
        return True
    else:
        return False
</pre>
<p>I left the original code in the function commented out so we can see the differences in the two methods here. In our original method we used the name space of redis itself to store the reference. In the updated fashion we are using redis&#8217;s hash data type to store the related fields.</p>
<pre class="brush: python;">
&gt;&gt;&gt; add_user(&quot;adam&quot;, &quot;Adam Smith&quot;, &quot;wealthofnations&quot;)
True
&gt;&gt;&gt; add_user(&quot;adam&quot;, &quot;Adam Smith&quot;, &quot;wealthofnations&quot;)
False
</pre>
<p>This function operates in the same fashion as our old version did but, is using a different data structure in the backend.</p>
<h2>Logging a user in</h2>
<p>Now we&#8217;ll refactor our old authentication code to work with the new backend.</p>
<pre class="brush: python;">
def authenticate_user(username, password):
    #if username in r.smembers(&quot;users&quot;):
    if r.sismember(&quot;users&quot;, username&quot;):
        passhash = md5(password).hexdigest()
        #if passhash == r.get(&quot;user:%s:password&quot; % username):
        if passhash == r.hget(&quot;user:%s&quot; % username, &quot;password&quot;):
            return True
        else:
            return False
    else:
        return False
</pre>
<p>Just as in the add_user function, we just need to make a small change. Now instead of fetching the related redis key we simply fetch the field from the hash of &#8220;user:*username*&#8221;.</p>
<pre class="brush: python;">
&gt;&gt;&gt; authenticate_user(&quot;adam&quot;, &quot;wealthofnations&quot;)
True
&gt;&gt;&gt; authenticate_user(&quot;adam&quot;, &quot;bad_password&quot;)
False
</pre>
<p>We can see the function again performs just like the old function but, it pulls the password from the hash object instead of the related key</p>
<h2>Deleting a user</h2>
<p>Deleting a user using the hash store is much easier than using the related key store, since everything is just stored in one key instead of being spread out across multiple keys.</p>
<pre class="brush: python;">
def delete_user(username):
    #if username in r.smembers(&quot;users&quot;):
    if r.sismembers(&quot;users&quot;, username):
        r.srem(&quot;users&quot;, username)
        r.delete(&quot;user:%s&quot; % username)
        #r.delete(&quot;user:%s:fullname&quot; % username)
        #r.delete(&quot;user:%s:password&quot; % username)
        return True
    else:
        return False
&lt;pre&gt;</pre>
<p>Now instead of having to delete the 2 related keys, we just need to delete the one key storing the hash of all of the user data</p>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/QRCmXo68qyg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/03/24/redis-relations-in-a-nosql-world-using-hashes/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/03/24/redis-relations-in-a-nosql-world-using-hashes/</feedburner:origLink></item>
		<item>
		<title>Redis: Relations in a NoSQL world</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/8rAhz1ysZg8/</link>
		<comments>http://degizmo.com/2010/03/23/redis-relations-in-a-nosql-world/#comments</comments>
		<pubDate>Tue, 23 Mar 2010 16:55:11 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Redis]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=25</guid>
		<description><![CDATA[In the first article in our series on Redis we talked about how to get started and the basics of the simple data structures that are available in redis. The simple structures are good for basic operations like storing strings and keeping counters but, using it for anything more complex requires relating one set of [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://degizmo.com/2010/03/22/getting-started-redis-and-python/">first article</a> in our series on <a href="http://code.google.com/p/redis/">Redis</a> we talked about how to get started and the basics of the simple data structures that are available in redis. The simple structures are good for basic operations like storing strings and keeping counters but, using it for anything more complex requires relating one set of data to another. At first glance this is a bit of a problem since redis by design is a flat dictionary with no relations but, with a bit of application code and adherence to some mental programming standards you can build some quite complex applications using redis.</p>
<p><span id="more-25"></span></p>
<p>We hinted at this style of structure in the first article when we got to talking about sets with our <a href="http://www.reddit.com/">reddit</a> like example of story voting.</p>
<pre class="brush: python;">
r_server.sadd(&quot;story:5419:upvotes&quot;, &quot;userid:9102&quot;)
</pre>
<p>Here we have a set in a redis called &#8220;story:5419:upvotes&#8221; and every element stored in the set is called &#8220;userid:xxxx&#8221;. This is an example of a basic relation.</p>
<p>Let&#8217;s make this example simpler and go with the concept of username / password storage for a website. Instead of using MySQL to store this information we will use redis.</p>
<h2>Relations in a NoSQL world</h2>
<p>We have to cheat in redis&#8217;s flat name space to make relations in our data. Redis isn&#8217;t going to be aware of these relations and unlike RDBMS (like MySQL), redis does nothing to help us out. No index&#8217;s, no nifty SQL syntax with WHERE or JOIN to do the work for us. We have to handle all of the relational logic in application code, which in turn means you (the developers) have to do extra documentation explaining just how everything fits together in redis or you are going to lose your data. The benefit you though is raw speed and flexibility during development. Don&#8217;t like the constraints one data model is giving you? Start over and just recode; no need to alter a DB schema or change a DB server; redis doesn&#8217;t care.</p>
<h2>Our requirements</h2>
<ul>
<li>Users have a username</li>
<li>Usernames have a password in a one-to-one fashion</li>
<li>We must be able to create a user and assign a password</li>
<li>Users must be able to login (check username against password)</li>
<li>We must be able to delete a username and their associated password</li>
</ul>
<h2>Designing our redis namespace</h2>
<p>This the format of the description of the redis namespace we&#8217;ll be using<br />
[<strong>key</strong>] &#8211; {<strong>datatype</strong>} &#8211; (example values)</p>
<p>We also will use the notation *variable* to denote that in a key name is a variable relating to something else.</p>
<p style="padding-left: 30px;">[users] &#8211; {set} &#8211; (&#8220;adam&#8221;, &#8220;bob&#8221;, &#8220;carol&#8221;)<br />
[user:*username*:fullname] &#8211; {string} &#8211; (&#8220;Adam Smith&#8221;, &#8220;Bob Barker&#8221;, &#8220;Carol Burnett&#8221;)<br />
[user:*username*:password] &#8211; {string} &#8211; (md5 hash password, no example)</p>
<p>That&#8217;s it. As long as we stick with this design pattern here we can keep track of all of the users in our system and handle logins.</p>
<h2>Creating a new user</h2>
<pre class="brush: python;">
r = redis.Redis(&quot;localhost&quot;)
from hashlib import md5

def add_user(username, fullname, password):
    if r.sadd(&quot;users&quot;, username):
        r.set(&quot;user:%s:fullname&quot; % username, fullname)
        r.set(&quot;user:%s:password&quot; % username, md5(password).hexdigest() )
        return True
    else:
        return False
</pre>
<p>We&#8217;ve created a function called add_user where we are taking in a username, the full name of the user, and password and will return True if we successfully create a new user and False if we don&#8217;t. Remember the redis command SADD (Set Add) returns False if the object already exists in the set, so if a user with that username already exists, we can&#8217;t create a new user so we return False; otherwise we add it to the set and then we set the associated keys &#8220;fullname&#8221; and &#8220;password&#8221; to the appropriate vaues. Hashing the password with a md5 hash since we never store passwords anywhere in plain text.</p>
<p>Let&#8217;s take a look at what this looks like being called.</p>
<pre class="brush: python;">
&gt;&gt;&gt; add_user(&quot;bob&quot;, &quot;Bob Barker&quot;, &quot;priceisright&quot;)
True
&gt;&gt;&gt; add_user(&quot;bob&quot;, &quot;Bob Barker&quot;, &quot;priceisright&quot;)
False
</pre>
<p>The first time we try to add the username &#8220;bob&#8221; we succeed but, the second time it fails since there is already a user with that username. Let&#8217;s look at the data stored in redis.</p>
<pre class="brush: python;">
&gt;&gt;&gt; r.smembers(&quot;users&quot;)
set(['bob'])
&gt;&gt;&gt; r.get(&quot;user:bob:fullname&quot;)
'Bob Barker'
&gt;&gt;&gt; r.get(&quot;user:bob:password&quot;)
'543f24fdc95f4e3f52fc7a4f2166167e'
</pre>
<p>We see our key &#8220;user&#8221; that has a set stored with only one element, our username &#8220;bob&#8221;. And now we have our related keys &#8220;user:*username*:fullname&#8221; and &#8220;user:*username*:password&#8221; which in practice are &#8220;user:bob:fullname&#8221; and &#8220;user:bob:password&#8221;. As long as we stick to the naming convention we should always know where everything is!</p>
<p>Let&#8217;s go ahead and create a few more users just for good measure</p>
<pre class="brush: python;">
&gt;&gt;&gt; add_user(&quot;adam&quot;, &quot;Adam Smith&quot;, &quot;wealthofnations&quot;)
True
&gt;&gt;&gt; add_user(&quot;carol&quot;, &quot;Carol Burnett&quot;, &quot;eartug&quot;)
True
&gt;&gt;&gt; r.smembers(&quot;users&quot;)
set(['carol', 'bob', 'adam'])
</pre>
<h2>Logging a user in</h2>
<p>Now that we have created our relational data store in redis and have a few users in there, lets try to log one in.</p>
<pre class="brush: python;">
def authenticate_user(username, password):
    #if username in r.smembers(&quot;users&quot;):
    if r.sismember(&quot;user&quot;, username):
        passhash = md5(password).hexdigest()
        if passhash == r.get(&quot;user:%s:password&quot; % username):
            return True
        else:
            return False
    else:
        return False
</pre>
<p>First thing we do is check to see if the username is <a href="http://docs.python.org/tutorial/datastructures.html#more-on-conditions">i</a>n the set of all of the elements in the key &#8220;users&#8221; using the method sismember (set &#8211; is a member). If the username isn&#8217;t there we are going to return False since, that user doesn&#8217;t even exist. If the user does exist, I take a hash of their submitted password just like we did when we added the user, then we fetch that password from the related key and see if they are the same, if they are, we return True!</p>
<p>Let&#8217;s take a look at this in action</p>
<pre class="brush: python;">
&gt;&gt;&gt; authenticate_user(&quot;ghost&quot;, &quot;idontexist!&quot;)
False
&gt;&gt;&gt; authenticate_user(&quot;adam&quot;, &quot;keynes&quot;)
False
&gt;&gt;&gt; authenticate_user(&quot;adam&quot;, &quot;wealthofnations&quot;)
True
&gt;&gt;&gt; authenticate_user(&quot;bob&quot;, &quot;priceisright&quot;)
True
</pre>
<p>So we can see here, a user that doesn&#8217;t exist is not authenticated. A user that does exist but, has the wrong password is denied. Given the right username and the right password a user gets in!. And just to show we can handle multiple users like a proper relational system should &#8220;bob&#8221; authenticates properly as well</p>
<h2>Deleting a user</h2>
<p>Eventually we are going to need to delete a user from our system and that is as easy everything else we have done as long as we stick to the same namespace we laid out before</p>
<pre class="brush: python;">
def delete_user(username):
    if username in r.smembers(&quot;users&quot;):
        r.srem(&quot;users&quot;, username)
        r.delete(&quot;user:%s:fullname&quot; % username)
        r.delete(&quot;user:%s:password&quot; % username)
        return True
    else:
        return False
</pre>
<p>Again the first thing we do is check that the user exists first, since if they don&#8217;t no need to do everything else. After we know the user exists, we remove them from the set of &#8220;users&#8221; then remove their related fullname and password keys. Let&#8217;s check this out in action</p>
<pre class="brush: python;">
&gt;&gt;&gt; authenticate_user(&quot;adam&quot;, &quot;wealthofnations&quot;)
True
&gt;&gt;&gt; delete_user(&quot;adam&quot;)
True
&gt;&gt;&gt; authenticate_user(&quot;adam&quot;, &quot;wealthofnations&quot;)
False
&gt;&gt;&gt; delete_user(&quot;adam&quot;)
False
&gt;&gt;&gt; r.smembers(&quot;users&quot;)
set(['bob', 'carol'])
</pre>
<p>We can authenticate the user &#8220;adam&#8221; properly. Then we delete him, and now he can&#8217;t authenticate any more. If we try to delete him again we see that we can&#8217;t since he doesn&#8217;t exist.</p>
<h2>Wrapping Up</h2>
<p>We can make very complex relational data structures in redis as long as we document and properly use the name space. Keep everything as simple and as straight forward as possible and document everything throughly. Also make sure all your actions on redis can be keep as modular as possible by wrapping them in functions or classes, just like in this example. Then if for some reason you need to alter your &#8220;schema&#8221; you only have one place to change it in your application.</p>
<h3>Footnote:</h3>
<p>This is an example and is not a secure method for handling user submitted data and does no sanitization or sanity checks on the information. I am aware of this but, this post was not designed to be a comprehensive analysis of AAA methods just a quick example of how to do basic relations in a key-value store.</p>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/8rAhz1ysZg8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/03/23/redis-relations-in-a-nosql-world/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/03/23/redis-relations-in-a-nosql-world/</feedburner:origLink></item>
		<item>
		<title>Getting Started: Redis and Python</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/zdp9PW9HyBU/</link>
		<comments>http://degizmo.com/2010/03/22/getting-started-redis-and-python/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 17:03:55 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Redis]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=4</guid>
		<description><![CDATA[So if you have been following NoSQL movement, the migration of some types of data to non-relational datastores has recently picked up speed. For web (and other developers) this has lead to some impressive engineering resources developing some amazing tools being open sourced for the world to use. One that caught my eye recently has been Salvatore [...]]]></description>
			<content:encoded><![CDATA[<p>So if you have been following <a href="http://en.wikipedia.org/wiki/NoSQL" target="_blank">NoSQL</a> movement, the migration of some types of data to non-relational datastores has recently picked up speed. For web (and other developers) this has lead to some impressive engineering resources developing some amazing tools being open sourced for the world to use. One that caught my eye recently has been <a href="http://invece.org/" target="_blank">Salvatore Sanfilippo&#8217;s</a> <a href="http://code.google.com/p/redis/" target="_blank">redis</a> which has been taken under the wing of <a href="http://blogs.vmware.com/console/2010/03/vmware-hires-key-developer-for-redis.html" target="_blank">VMWare</a>, solidifying and validating the great work that Salavatore has done making redis an amazing tool in any developers arsenal.</p>
<p>A very simplified explanation of redis is that it is an in memory key-value store like <a href="http://memcached.org/" target="_blank">memcached</a> but, it is persistent on disk, unlike memcached which is volatile. Along with being disk-persistent redis also supports some basic <a href="http://code.google.com/p/redis/wiki/IntroductionToRedisDataTypes" target="_blank">data structures</a> like lists, sets, ordered sets, hashes, and of course basic key-value string storage like memcached. Redis, with disk-persistence and basic data structures, remains blazing fast with published benchmarks of <a href="http://code.google.com/p/redis/wiki/Benchmarks" target="_blank">110,000 SETs per second, about 81,000 GETs per second</a>.</p>
<p>This post is the start of a <a href="http://degizmo.com/series-redis-tutorials/" target="_self">series of articles on redis</a> for Python programmers. A prerequisite for this is going to be some basic Python knowledge, which if you haven&#8217;t used before I highly recommend the free web book <a href="http://www.diveintopython.org/toc/index.html">Dive Into Python</a>. This is going to be a simple overview of the basic data types and usage for Python programmers and we will slowly progress into more complex usages, so if you haven&#8217;t done anything with redis before this is a perfect start.</p>
<p><span id="more-4"></span></p>
<h2><strong>Installing Redis</strong></h2>
<p>Redis is extremely easy to install on POSIX systems (Linux, OSX, Cygwin for Windows). Simply download either a release version or checkout the trunk version of redis from the <a href="http://code.google.com/p/redis/" target="_blank">project home page</a>. Unpackage, make, and run. That&#8217;s it!</p>
<pre class="brush: bash;">
gettingstarted $ wget http://redis.googlecode.com/files/redis-1.2.5.tar.gz
gettingstarted $ gunzip redis-1.2.5.tar.gz
gettingstarted $ tar -xvf redis-1.2.5.tar
gettingstarted $ cd redis-1.2.5
redis-1.2.5 $ make
redis-1.2.5 $ ./redis-server
21 Mar 17:37:11 * Warning: no config file specified, using the default config. In order to specify a config file use 'redis-server /path/to/redis.conf'
21 Mar 17:37:11 - Server started, Redis version 1.2.5
21 Mar 17:37:11 - The server is now ready to accept connections on port 6379
21 Mar 17:37:11 . 0 clients connected (0 slaves), 832496 bytes in use, 0 shared objects
</pre>
<p>6 commands and redis is running and ready for a connection. Obviously this isn&#8217;t best practice for running redis in production but, it works well for just getting it up and running for some experimentation. Let&#8217;s leave that window open and open another for a Python console.</p>
<p>In every example below we only are covering the basic operations of each type. If you want to learn about all of the possible operations for redis read up on the redis <a href="http://code.google.com/p/redis/wiki/CommandReference" target="_blank">Command Reference</a>. This has all of the commands available to you.</p>
<h2><strong>Redis and Python</strong></h2>
<p>First thing we need is the <a href="http://github.com/andymccurdy/redis-py/" target="_blank">redis-py</a> module for Python. You can install this manually or just use easy_install.</p>
<pre class="brush: bash;">
easy_install redis
</pre>
<h3><strong>Everything has a place: keys</strong></h3>
<p>Redis is a <a href="http://en.wikipedia.org/wiki/Associative_array" target="_blank">key-value store</a> just like a <a href="http://docs.python.org/tutorial/datastructures.html#dictionaries" target="_blank">Python dictionary</a>. So everything that goes into redis no matter what it is, has a key (or location, or address, whatever makes sense to you). You can&#8217;t store something without a place for it to go</p>
<p>Now let&#8217;s open up a Python console and start to play with the basic data structures</p>
<h3><strong>Data structure: String</strong></h3>
<p>The most basic data structure in redis is the string. Simply, you have a key and it stores a string.</p>
<pre class="brush: python;">
&gt;&gt;&gt; import redis
&gt;&gt;&gt; r_server = redis.Redis(&quot;localhost&quot;)
&gt;&gt;&gt; r_server.set(&quot;name&quot;, &quot;DeGizmo&quot;)
True
&gt;&gt;&gt; r_server.get(&quot;name&quot;)
'DeGizmo'
</pre>
<p>So, line by line let&#8217;s walk through what we&#8217;ve done here.</p>
<ol>
<li>import the redis module</li>
<li>create an object called &#8220;r_server&#8221; of redis.Redis type with the parameter &#8220;localhost&#8221; which is the network location of our running redis server</li>
<li>call the function &#8220;set&#8221; on the &#8220;r_server&#8221; object with the parameters &#8220;name&#8221; and &#8220;DeGizmo&#8221;. The first parameter &#8220;name&#8221; is the <strong>key</strong> and &#8220;DeGizmo&#8221; is the <strong>value</strong>. So in redis we created a key-value pair of &#8220;name&#8221; -&gt; &#8220;DeGizmo&#8221;</li>
<li>call the function &#8220;get&#8221; which will retrieve the value from the key which is passed as the parameter. We are getting the key &#8220;name&#8221; and redis returns the value &#8220;DeGizmo&#8221;</li>
</ol>
<p>That&#8217;s it. If you go and stop the redis server and restart it and run r_server.get(&#8220;name&#8221;) command again, it will return &#8220;DeGizmo&#8221; again due to redis&#8217;s persistent store.</p>
<h3><strong>Data structure: Integer</strong></h3>
<p>The second data type available is an integer.</p>
<pre class="brush: python;">
&gt;&gt;&gt; r_server.set(&quot;hit_counter&quot;, 1)
True
&gt;&gt;&gt; r_server.incr(&quot;hit_counter&quot;)
2
&gt;&gt;&gt; r_server.get(&quot;hit_counter&quot;)
'2'
&gt;&gt;&gt; r_server.decr(&quot;hit_counter&quot;)
1
&gt;&gt;&gt; r_server.get(&quot;hit_counter&quot;)
'1'
</pre>
<p>Again using the &#8220;r_server&#8221; Redis object we run the following commands</p>
<ol>
<li>We set the redis key &#8220;hit_counter&#8221; to a value of 1 just like in the example above</li>
<li>Then we run the command &#8220;incr&#8221; on the key &#8220;hit_counter&#8221;. This will increment (incr) the key by 1</li>
<li>We get the value for the key &#8220;hit_counter&#8221; to verify that it was been incremented</li>
<li>Then we run the command &#8220;decr&#8221; on the key &#8220;hit_counter&#8221;. This will decrement (decr) the key by 1</li>
<li>We get the value for the key &#8220;hit_counter&#8221; to verify that it was been decremented</li>
</ol>
<p>Simple huh? Well remember that redis is a persistent store that can be accessed by multiple machines (or programs) simultaneously. If you have a horizontally scaled web farm with many different web servers running on separate machines, your web app can all call on and reference the same redis instance and all operate on the &#8220;hit_counter&#8221; key at the same time and increment it just like how you would use a MySQL database. You can kind of think of redis like a &#8220;shared&#8221; storage across different applications.</p>
<h3><strong>Data structure: Lists</strong></h3>
<p>Very similar to the built in <a href="http://docs.python.org/tutorial/datastructures.html#more-on-lists" target="_blank">Python list type</a>, the redis list type has a few basic methods that combined can quite powerful. We are only covering a tiny portion of the commands available, you can find all the commands in the redis <a href="http://code.google.com/p/redis/wiki/CommandReference" target="_blank">Command Reference</a>.</p>
<pre class="brush: python;">
&gt;&gt;&gt; r_server.rpush(&quot;members&quot;, &quot;Adam&quot;)
True
&gt;&gt;&gt; r_server.rpush(&quot;members&quot;, &quot;Bob&quot;)
True
&gt;&gt;&gt; r_server.rpush(&quot;members&quot;, &quot;Carol&quot;)
True
&gt;&gt;&gt; r_server.lrange(&quot;members&quot;, 0, -1)
['Adam', 'Bob', 'Carol']
&gt;&gt;&gt; r_server.llen(&quot;members&quot;)
3
&gt;&gt;&gt; r_server.lindex(&quot;members&quot;, 1)
'Bob'
</pre>
<p>We don&#8217;t actually have to create or declare anything when using redis, we just use it and redis handles everything else for us. So we just go ahead and tell redis at the key &#8220;members&#8221; we are going to add (rpush, right push) the value &#8220;Adam&#8221;. Redis creates the list for us at key &#8220;members&#8221; and adds the value &#8220;Adam&#8221; to the list.</p>
<ol>
<li>With the r_server object again we call the method &#8220;rpush&#8221; which will add the value &#8220;Adam&#8221; to the newly created list &#8220;members&#8221;</li>
<li>We add &#8220;Bob&#8221; to the same list</li>
<li>Finally we&#8217;ll add &#8220;Carol&#8221;</li>
<li>With the lrange method we are asking redis to return all the objects in &#8220;members&#8221;. lrange takes 3 arguments: key, start index in list, end index in list. We are getting the objects from the key &#8220;members&#8221; starting at index 0 and ending at -1 (which is technically the -1, or last index in the list, which will return everything)</li>
<li>The llen method asks redis to return the length of the list at the key &#8220;members&#8221; which now has 3 objects</li>
<li>lindex method tells redis that we want the object from the key &#8220;members&#8221; at the index position of 1 (remember lists start at index 0), so redis returns &#8220;Bob&#8221;</li>
</ol>
<p>We&#8217;ve got some elements in the list at the key &#8220;members&#8221;; now lets get remove some elements.</p>
<pre class="brush: python;">
&gt;&gt;&gt; r_server.rpop(&quot;members&quot;)
'Carol'
&gt;&gt;&gt; r_server.lrange(&quot;members&quot;, 0, -1)
['Adam', 'Bob']
&gt;&gt;&gt; r_server.lpop(&quot;members&quot;)
'Adam'
&gt;&gt;&gt; r_server.lrange(&quot;members&quot;, 0, -1)
['Bob']
</pre>
<ol>
<li>With the method rpop (right pop) we remove the element in the list on the right side (tail), which is &#8220;Carol&#8221;</li>
<li>Now when we ask for the list &#8220;members&#8221; from redis again (from the start of 0, and the end of -1 which returns everything) we see our list now doesn&#8217;t have &#8220;Carol&#8221;</li>
<li>We now lpop (left pop) an element from the list &#8220;members&#8221;. This will remove the far left element from the list, &#8220;Adam&#8221;</li>
<li>Now the entire list only contains &#8220;Bob&#8221;</li>
</ol>
<h3><strong>Data structure: Set</strong></h3>
<p>Again, sets perform identically to the <a href="http://docs.python.org/tutorial/datastructures.html#sets" target="_blank">built in Python set type</a>. Simply, sets are lists but, can only have unique values. In the above example if we added the value Adam (r_server.lpush(&#8220;members&#8221;, &#8220;Adam&#8221;) ) 20 times our list would contain 20 values all containing the value &#8220;Adam&#8221;. In a set, all elements are unique.</p>
<pre class="brush: python;">
&gt;&gt;&gt; r_server.delete(&quot;members&quot;)
True
&gt;&gt;&gt; r_server.sadd(&quot;members&quot;, &quot;Adam&quot;)
True
&gt;&gt;&gt; r_server.sadd(&quot;members&quot;, &quot;Bob&quot;)
True
&gt;&gt;&gt; r_server.sadd(&quot;members&quot;, &quot;Carol&quot;)
True
&gt;&gt;&gt; r_server.sadd(&quot;members&quot;, &quot;Adam&quot;)
False
&gt;&gt;&gt; r_server.smembers(&quot;members&quot;)
set(['Bob', 'Adam', 'Carol'])
</pre>
<ol>
<li>First off we delete the old list in the key &#8220;members&#8221; so we can use it as a set</li>
<li>Then we sadd (set add) the value &#8220;Adam&#8221; to the key &#8220;members&#8221;</li>
<li>Do the same for the value &#8220;Bob&#8221;</li>
<li>Do the same for the value &#8220;Carol&#8221;</li>
<li>Now we try to add the value &#8220;Adam&#8221; to the key &#8220;members&#8221; again but, this time it returns &#8220;False&#8221; since we are working on a set, and a set only has unique values. There already is a value &#8220;Adam&#8221; present in this set</li>
<li>The method smembers returns all the members of the set in the Python type set</li>
</ol>
<p>An example of a use of sets in a web application would be for &#8220;upvotes&#8221; on a <a href="http://www.reddit.com/" target="_blank">reddit</a>, or <a href="http://news.ycombinator.com/" target="_blank">hacker news</a> type website. We want to keep track of who up votes a story but, you should only be able to up vote a story once.</p>
<pre class="brush: python;">
&gt;&gt;&gt; r_server.sadd(&quot;story:5419:upvotes&quot;, &quot;userid:9102&quot;)
True
&gt;&gt;&gt; r_server.sadd(&quot;story:5419:upvotes&quot;, &quot;userid:12981&quot;)
True
&gt;&gt;&gt; r_server.sadd(&quot;story:5419:upvotes&quot;, &quot;userid:1233&quot;)
True
&gt;&gt;&gt; r_server.sadd(&quot;story:5419:upvotes&quot;, &quot;userid:9102&quot;)
False
&gt;&gt;&gt; r_server.scard(&quot;story:5419:upvotes&quot;)
3
&gt;&gt;&gt; r_server.smembers(&quot;story:5419:upvotes&quot;)
set(['userid:12981', 'userid:1233', 'userid:9102'])
</pre>
<p>I added a little twist in here with the name of the key: &#8220;story:5419:upvotes&#8221; but, it&#8217;s easy to explain. Redis is &#8220;flat&#8221; with it&#8217;s keyspace. So if we have many different stories we use a fixed key naming convention for easy reference in redis. For this example our key is broken down like this: &#8220;object type&#8221; : &#8220;id&#8221; : &#8220;attribute&#8221;. So, we have an object of type &#8220;story&#8221; with an ID of &#8220;5419&#8243; with an attribute &#8220;upvotes&#8217;. Redis has no idea what any of this means it just knows the key is &#8220;story:5419:upvotes&#8221; but, it doesn&#8217;t matter, we know what it means and we can divide up our objects into this name space to make it easier to work with and keep from &#8220;losing&#8221; things. The value being added to the key is divided up in the same way. &#8220;userid&#8221; is the type and &#8220;9102&#8243; is the value or the ID for that user voting on the story.</p>
<ol>
<li>Just like before we are adding the value &#8220;userid:9102&#8243; to the key &#8220;story:5419:upvotes&#8221;</li>
<li>Now we are adding the value &#8220;userid:12981&#8243;</li>
<li>Finally adding the valud &#8220;userid:1233&#8243;</li>
<li>Now, the user with the ID 9102 tries to up vote the story with the ID 5419 again, and redis returns False since that user has already up votes this story before and you can&#8217;t up vote a story twice!</li>
<li>The method &#8220;scard&#8221; is asking redis for the <a href="http://en.wikipedia.org/wiki/Cardinality" target="_blank">cardinality</a> of the set at key &#8220;story:5419:upvotes&#8221; or how many things are in this set, and redis returns 3.</li>
<li>Finally we return the list of userid&#8217;s that we have stored in the set.</li>
</ol>
<h3><strong>Data structure: Ordered sets</strong></h3>
<p>The last data structure we are going to talk about today is an ordered (or sorted) set. This operates just like a set but, has an extra attribute when we add something to a set called a &#8220;score&#8221;. This score determines the order of the elements in the set. We will stick with the concept for this final example</p>
<pre class="brush: python;">
&gt;&gt;&gt; r_server.zadd(&quot;stories:frontpage&quot;, &quot;storyid:3123&quot;, 34)
True
&gt;&gt;&gt; r_server.zadd(&quot;stories:frontpage&quot;, &quot;storyid:9001&quot;, 3)
True
&gt;&gt;&gt; r_server.zadd(&quot;stories:frontpage&quot;, &quot;storyid:2134&quot;, 127)
True
&gt;&gt;&gt; r_server.zadd(&quot;stories:frontpage&quot;, &quot;storyid:2134&quot;, 127)
False
&gt;&gt;&gt; r_server.zrange(&quot;stories:frontpage&quot;, 0, -1, withscores=True)
[('storyid:9001', 3.0), ('storyid:3123', 34.0), ('storyid:2134', 127.0)]
&gt;&gt;&gt; frontpage = r_server.zrange(&quot;stories:frontpage&quot;, 0, -1, withscores=True)
&gt;&gt;&gt; frontpage.reverse()
&gt;&gt;&gt; frontpage
[('storyid:2134', 127.0), ('storyid:3123', 34.0), ('storyid:9001', 3.0)]
</pre>
<p>Quick namespace explanation like before. For the key we are going to be referring to &#8220;stories:frontpage&#8221; which is going to be a set of stories slated for the front page of our website. We are storing in that key the value of &#8220;storyid:3123&#8243; which is the ID of some story on the site and then a score, which in our case is going to be the number of votes on a story.</p>
<ol>
<li>First we add the value &#8220;storyid:3123&#8243; to &#8220;stories:frontpage&#8221;, and &#8220;storyid:3123&#8243; in our example is going to have 34 votes.</li>
<li>Then add &#8220;storyid:9001&#8243; with 3 votes</li>
<li>Then add &#8220;storyid:2134&#8243; with 127 votes</li>
<li>We are going to try to add &#8220;story:2134&#8243; to the set again but, we can&#8217;t since it already exists.</li>
<li>Now we are going to ask redis for all the elements in &#8220;stories:frontpage&#8221; from index 0 to index -1 (the end of the list) with all associated scores (withscores=True)</li>
<li>We&#8217;ve got the scores but, they are in ascending order, we want them in descending order for our website, so we are going to store the results in the variable &#8220;frontpage&#8221;</li>
<li>Then reverse it (which is an in place operation in Python)</li>
<li>Now print out the front page!</li>
</ol>
<p>In conclusion let&#8217;s do a quick example of a &#8220;view&#8221; in an application in which a user will vote of a story using redis as a storage engine</p>
<pre class="brush: python;">
#given variables
#r_server   = our redis server
#user_id    = the user who voted on the story
#story_id   = the story which the user voted on
if r_server.sadd(&quot;story:%s&quot; % story_id, &quot;userid:%s&quot; % user_id):
    r_server.zincrby(&quot;stories:frontpage&quot;, &quot;storyid:%s&quot; % story_id, 1)
</pre>
<p>2 lines of code? This is might compact but, once we unravel it we can see how it makes sense and how powerful redis can be. Let&#8217;s start with the if statement.</p>
<pre class="brush: python;">
if r_server.sadd(&quot;story:%s&quot; % story_id, &quot;userid:%s&quot; % user_id):
</pre>
<p>We know the command &#8220;sadd&#8221; already. This will add an element to a set at a key. The key in this case is</p>
<pre class="brush: python;">
&quot;story:%s&quot; % story_id
</pre>
<p>If story_id is 3211, then the resulting string will be &#8220;story:3211&#8243;. This is the key in redis which contains the list of users that has voted on the story.</p>
<p>The value to be inserted at this key is</p>
<pre class="brush: python;">
&quot;userid:%s&quot; % user_id
</pre>
<p>Just like with story, if the user_id is 9481 then the string to be inserted into the set at &#8220;story:3211&#8243; will be &#8220;user_id:9481&#8243;</p>
<p>Now the redis command &#8220;sadd&#8221; will return False if that element is already present in the set. So if a user has already voted on this story before we don&#8217;t execute the statement under the if. But, if it is added, then we have a brand new vote and we have to increment the votes for the front page.</p>
<pre class="brush: python;">
r_server.zincrby(&quot;stories:frontpage&quot;, &quot;storyid:%s&quot; % story_id, 1)
</pre>
<p>We have an ordered set at the key &#8220;stories:frontpage&#8221; and we are going to increment the element &#8220;storyid:%s&#8221; % story_id (&#8220;story:3211&#8243;) by 1.</p>
<p>And now we&#8217;re done! We&#8217;ve made sure the user hasn&#8217;t voted on this story before and then we&#8217;ve incremented the number of votes for this story on the front page!</p>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/zdp9PW9HyBU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/03/22/getting-started-redis-and-python/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/03/22/getting-started-redis-and-python/</feedburner:origLink></item>
		<item>
		<title>Tutorial: Writing our first views</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/RQomxypaPm0/</link>
		<comments>http://degizmo.com/2010/03/21/tutorial-writing-our-first-views/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 02:47:34 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=22</guid>
		<description><![CDATA[So far in the tutorial we&#8217;ve started our project, setup the database, enabled the admin interface, created models for our blog, and we just did a brief tutorial on Django&#8217;s ORM and DB-API. Now let&#8217;s look at getting data out of our database and onto the web page using views.
This section will be a bit short because we won&#8217;t really be using [...]]]></description>
			<content:encoded><![CDATA[<p>So far in the <a href="http://degizmo.com/series-django-tutorials/">tutorial</a> we&#8217;ve <a href="http://degizmo.com/2010/03/15/tutorial-starting-a-project/">started our project</a>, <a href="http://degizmo.com/2010/03/16/tutorial-setting-up-the-database/">setup the database</a>, <a href="http://degizmo.com/2010/03/17/tutorial-the-admin-interface/">enabled the admin interface</a>, <a href="http://degizmo.com/2010/03/18/tutorial-create-our-models/">created models for our blog</a>, and we just did a brief tutorial on Django&#8217;s <a href="http://degizmo.com/2010/03/20/tutorial-learning-the-db-api-and-orm/">ORM and DB-API</a>. Now let&#8217;s look at getting data out of our database and onto the web page using <a href="http://simpledjango.com/blog/2009/03/quick-reference-views/" class="broken_link" >views</a>.</p>
<p>This section will be a bit short because we won&#8217;t really be using templates, which we&#8217;ll cover in the next section. We will just be looking at how the urls.py file and the views.py file interact and how we can use what we learned in our <a href="http://degizmo.com/2010/03/20/tutorial-learning-the-db-api-and-orm/">ORM</a> tutorial not in the shell but, in our application.</p>
<p><span id="more-22"></span></p>
<p>So remember our urls.py file from the <a href="http://degizmo.com/2010/03/17/tutorial-the-admin-interface/">admin interface tutorial</a>?</p>
<pre class="brush: python;">
from django.conf.urls.defaults import *

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    (r'^admin/', include(admin.site.urls)),
)
</pre>
<p>It&#8217;s pretty sparse and doesn&#8217;t do much. Let&#8217;s make a home page</p>
<pre class="brush: python;">
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()

from main.views import *

urlpatterns = patterns('',
    (r'^admin/',            include(admin.site.urls)),
    (r'^$',                 home),
)
</pre>
<p>We&#8217;ve added two lines here. The first &#8220;from main.views import *&#8221; is importing all the functions that are in the views file for the main application in our blog project (right now there are no applications). The second line I&#8217;ve added, &#8220;(r&#8217;^$&#8217;, home),&#8221;, is a tuple that I&#8217;ve added to the urlpatterns variable. This variable is where Django looks to find all the URL&#8217;s our project uses. The first part of the tuple is a regex expression for basically, nothing. It&#8217;s what happens when you just hit the domain of our site (like simpledjango.com). The second part of the tuple is the function &#8220;home&#8221;. If you goto your development server at <a href="http://127.0.0.1:8000">http://127.0.0.1:8000</a>you&#8217;ll see a Name Error. This function isn&#8217;t defined so lets go to the views.py in the main application (blog/main/views.py) and add the function home.</p>
<pre class="brush: python;">
# Create your views here.
def home(request):
    pass
</pre>
<p>This is what my views.py file looks like now. When we refresh our development server you&#8217;ll see a new error.</p>
<blockquote><p>ValueError at /<br />
The view blog.main.views.home didn&#8217;t return an HttpResponse object.</p></blockquote>
<p>Django requires <a href="http://simpledjango.com/blog/2009/03/quick-reference-response/" class="broken_link" >response object</a> to be returned from every view. Let&#8217;s import the HttpResponse object and have our function return it.</p>
<pre class="brush: python;">
# Create your views here.
from django.http import HttpResponse
def home(request):
    return HttpResponse()
</pre>
<p>If we refresh our page again we&#8217;ll see the error is gone and we now have a blank page. Let&#8217;s type something in the HttpResponse object and see what happens</p>
<pre class="brush: python;">
# Create your views here.
from django.http import HttpResponse
def home(request):
    return HttpResponse(&quot;testing, testing 1 2 3 &quot;)
</pre>
<p>Refresh the page and we&#8217;ll see &#8220;testing, testing 1 2 3&#8243; on our page. Anything that is passed into the HttpResponse object instance will essentially be passed along to our browser.</p>
<p>Let&#8217;s get some data out of our database and pass it along. Let&#8217;s try to display all the categories that we have</p>
<pre class="brush: python;">
# Create your views here.
from django.http import HttpResponse
from main.models import Category
def home(request):
    cats = Category.objects.all()
    return HttpResponse(cats)
</pre>
<p>The first difference you&#8217;ll see is the &#8220;from main.models import Category&#8221;. Here we are importing the model Category that we created in our <a href="http://degizmo.com/2010/03/18/tutorial-create-our-models/">models tutorial</a> so we can use it in our view here. Then just like in the <a href="http://degizmo.com/2010/03/20/tutorial-learning-the-db-api-and-orm/">DB-API tutorial</a> we are storing all the categories in a variable called cats then passing that into the HttpResponse object instantiation. When we refresh our home page we&#8217;ll see all of our categories listed out, although in a quite ugly fashion.</p>
<p>So as you can see getting data from our database back to the web browser is really just the same thing as using it via the DB-API in the shell. I said this would be a short tutorial since the focus was really just bringing together the concepts of using the database via the ORM and taking it out of the shell into our web application.</p>
<p>The next tutorial will talk about how we can really use the information in the DB on web pages using templates. <strong>(Coming Soon)</strong></p>
<h3>Download at this step: <a href="http://github.com/degizmo/django-tutorial/zipball/b558c1f5a2453d0ee8417305e9e9f6874f80dd22">GitHub</a></h3>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/RQomxypaPm0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/03/21/tutorial-writing-our-first-views/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/03/21/tutorial-writing-our-first-views/</feedburner:origLink></item>
		<item>
		<title>Tutorial: Learning the DB-API and ORM</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/adxd24XjR24/</link>
		<comments>http://degizmo.com/2010/03/20/tutorial-learning-the-db-api-and-orm/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 02:41:41 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=20</guid>
		<description><![CDATA[So far in the tutorial we&#8217;ve started our project, setup the database, enabled the admin interface, created models for our blog. We&#8217;re going to slow down on actually developing our blog and talk about exactly how we get to the data we&#8217;ve stored in the database so far. The Admin Interface is great but, it doesn&#8217;t provide good programtic [...]]]></description>
			<content:encoded><![CDATA[<p>So far in the <a href="http://degizmo.com/series-django-tutorials/">tutorial</a> we&#8217;ve <a href="http://degizmo.com/2010/03/15/tutorial-starting-a-project/">started our project</a>, <a href="http://degizmo.com/2010/03/16/tutorial-setting-up-the-database/">setup the database</a>,<a href="http://degizmo.com/2010/03/17/tutorial-the-admin-interface/"> enabled the admin interface</a>, <a href="http://simpledjango.com/blog/2009/03/tutorial-the-admin-interface/" class="broken_link" ></a><a href="http://degizmo.com/2010/03/18/tutorial-create-our-models/">created models for our blog</a>. We&#8217;re going to slow down on actually developing our blog and talk about exactly how we get to the data we&#8217;ve stored in the database so far. The Admin Interface is great but, it doesn&#8217;t provide good programtic access to the data. Let&#8217;s open up a python shell but, we&#8217;re going to do it a special way when working with Django. From the command line in our root project directory (blog/)</p>
<pre class="brush: python;">
$ python manage.py shell
Python 2.5 (r25:51918, Sep 19 2006, 08:49:13)
[GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
(InteractiveConsole)
&gt;&gt;&gt;
</pre>
<p>Now this might look like a normal Python shell because, well it is. We&#8217;ve just loaded up some stuff in the background like path information to make our lives a bit easier. Now we have two models that we created in the application &#8220;main&#8221;. Let&#8217;s load those up in the shell.</p>
<p><span id="more-20"></span></p>
<pre class="brush: python;">
&gt;&gt;&gt; from main.models import Category
&gt;&gt;&gt; from main.models import BlogPost
</pre>
<p>Before we get too deep here, I want to mention that everything that we do in the shell we can do in our application. It&#8217;s the same thing. So any manipulation we make here we can use the exact same code anywhere in our application. The shell is a great way to test out ideas and algorithms before we put that code into our application. We have our two models loaded up lets play with the built in &#8220;objects&#8221; Manager.</p>
<pre class="brush: python;">
&gt;&gt;&gt; BlogPost.objects.all()
[&lt;BlogPost: Our First Post&gt;]
&gt;&gt;&gt; Category.objects.all()
[&lt;Category: Books&gt;]
</pre>
<p>For both of our models we are calling the function all() in the object manager. This will return a special Django object called a QuerySet. These are very powerful objects which we&#8217;ll see in a second. Let&#8217;s get all of the posts for a specific category.</p>
<pre class="brush: python;">
&gt;&gt;&gt; Category.objects.all()
[&lt;Category: Books&gt;]
&gt;&gt;&gt; cat = Category.objects.all()[0]
&gt;&gt;&gt; cat
&lt;Category: Books&gt;
</pre>
<p>Now even though objects.all() returns an object called a QuerySet it also works just like a standard array. So I&#8217;ve just taken the first element of the array &#8220;[0]&#8221; and assigned it to cat. So now we have a variable &#8220;cat&#8221; which contains one of our Categories called &#8220;Books&#8221;. We can see that the category has a Name which is called &#8220;Books&#8221;. Remember when we defined our __unicode__ object back in the <a href="http://degizmo.com/2010/03/18/tutorial-create-our-models/">create our models</a> part. This is why python is calling our object . If we hadn&#8217;t defined the __unicode__ function python would print out our object like this:&lt;Category: Category object&gt;</p>
<p>Now that we have a specific category lets find all the blog posts associated with that category. I&#8217;m going to show you two different ways of doing this just show you two different new things.</p>
<pre class="brush: python;">
&gt;&gt;&gt; BlogPost.objects.filter(Category=cat)
[&lt;BlogPost: Our First Post&gt;]

&gt;&gt;&gt; all_blog_posts = BlogPost.objects.all()
&gt;&gt;&gt; all_blog_posts
[&lt;BlogPost: Our First Post&gt;]
&gt;&gt;&gt; all_blog_posts.filter(Category=cat)
[&lt;BlogPost: Our First Post&gt;]
</pre>
<p>In the first line of code we are taking the same BlogPost.objects but, instead of calling all() we are calling filter. Filter is a function where we can compare any field from our model declaration in models.py and find only things that match that comparison. So here we are finding all the BlogPost that have a Category=cat (which is Category: Books).</p>
<p>The second example we are taking all the objects from BlogPost and putting them into all_blog_posts. Now this is a QuerySet object we mentioned before. It has the same methods as all of our model&#8217;s. So I can simple just filter that QuerySet for all of the posts that are in the Category : Books. The result of BOTH of those examples is still a QuerySet so I can filter them again, and again. There are a lot of functions in QuerySet&#8217;s that are very cool. We only touch on a very of them here. For a more in depth look goto our <a href="http://simpledjango.com/blog/2009/03/quick-reference-querysets/" class="broken_link" >Quick Reference: QuerySets</a></p>
<p>So we&#8217;ve seen the basic ways to retrieve objects. Let&#8217;s create a new BlogPost from the shell.</p>
<pre class="brush: python;">
&gt;&gt;&gt; from django.contrib.auth.models import User
&gt;&gt;&gt; User.objects.all()
[&lt;User: DeGizmo&gt;]
&gt;&gt;&gt; degizmo = User.objects.all()[0]

&gt;&gt;&gt; new_post = BlogPost()
&gt;&gt;&gt; new_post.Title = &quot;blog post from the shell&quot;
&gt;&gt;&gt; new_post.Category = cat
&gt;&gt;&gt; new_post.Slug = &quot;this-slug-shell&quot;
&gt;&gt;&gt; new_post.PostText = &quot;this is the text of the blog post!&quot;
&gt;&gt;&gt; new_post.Author = degizmo
&gt;&gt;&gt; new_post.save()
&gt;&gt;&gt; BlogPost.objects.all()
[&lt;BlogPost: Our First Post&gt;, &lt;BlogPost: blog post from the shell&gt;]
</pre>
<p>The first thing we did was import the model &#8220;User&#8221; which we used before when we declared our model. Then I selected myself (the only user) and assigned it to the variable &#8220;adam&#8221;.</p>
<p>Now I created a new BlogPost object called new_post and went through each field in the model and assigned it a value. Then I called the function .save() which saves the new object to our database. Which you can see when we look at all of the objects stored in BlogPost. Go check the admin interface and you&#8217;ll see our new BlogPost right there along side of the rest of them.</p>
<p>Let&#8217;s say we want to change the title of that blog post for some reason (maybe we don&#8217;t like the capitalization).</p>
<pre class="brush: python;">
&gt;&gt;&gt; BlogPost.objects.all()
[&lt;BlogPost: Our First Post&gt;, &lt;BlogPost: blog post from the shell&gt;]
&gt;&gt;&gt; BlogPost.objects.get(Title=&quot;blog post from the shell&quot;)
&lt;BlogPost: blog post from the shell&gt;

&gt;&gt;&gt; edit = BlogPost.objects.get(Title=&quot;blog post from the shell&quot;)
&gt;&gt;&gt; edit.Title = &quot;Blog Post From The Shell!&quot;
&gt;&gt;&gt; edit.save()
&gt;&gt;&gt; BlogPost.objects.all()
[&lt;BlogPost: Our First Post&gt;, &lt;BlogPost: Blog Post From The Shell!&gt;]
</pre>
<p>So once again we look at all of our BlogPost objects. This time I use a different function called get. This function doesn&#8217;t return a QuerySet but, just a single object from the database. It works the same way as filter, you tell it which field you want to compare in the database and it will return the right object. I just used the post title we want to change. Once I have stored the right post in the variable &#8220;edit&#8221; I edit the field &#8220;Title&#8221; then save it to back to the database with the function call save()</p>
<p>Maybe we don&#8217;t like that post at all anymore so let&#8217;s delete it.</p>
<pre class="brush: python;">
&gt;&gt;&gt; BlogPost.objects.all()
[&lt;BlogPost: Our First Post&gt;, &lt;BlogPost: Blog Post From The Shell!&gt;]
&gt;&gt;&gt; edit = BlogPost.objects.get(Title=&quot;Blog Post From The Shell!&quot;)
&gt;&gt;&gt; edit
&lt;BlogPost: Blog Post From The Shell!&gt;
&gt;&gt;&gt; edit.delete()
&gt;&gt;&gt; BlogPost.objects.all()
[&lt;BlogPost: Our First Post&gt;]
</pre>
<p>I got the BlogPost I wanted the same way as before using the &#8220;get&#8221; function, stored it in the variable edit. Then just called the function delete()</p>
<p>From the console we&#8217;ve returned all the categories, blog posts, posts just for a category, a single blog post, edited a blog post and deleted a blog post. Without writing a single line of SQL. Odds are you&#8217;ll almost never have to write a single line of SQL while working in Django unless you have some really complex models.</p>
<p>Now that we know how to get data out of the database <a href="http://degizmo.com/2010/03/21/tutorial-writing-our-first-views/">let&#8217;s write our first view</a></p>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/adxd24XjR24" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/03/20/tutorial-learning-the-db-api-and-orm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/03/20/tutorial-learning-the-db-api-and-orm/</feedburner:origLink></item>
		<item>
		<title>Tutorial: Create our models</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/flIwX39VW6A/</link>
		<comments>http://degizmo.com/2010/03/18/tutorial-create-our-models/#comments</comments>
		<pubDate>Fri, 19 Mar 2010 02:35:29 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=18</guid>
		<description><![CDATA[So far in the tutorial we&#8217;ve started our project, setup the database, enabled the admin interface and now we&#8217;re ready to start to define the database for our project, a simple blog.
This is where we will start working with the models.py file in the &#8220;main&#8221; application directory (blog/main/). The models.py file is a definition file where we tell Django what all of our [...]]]></description>
			<content:encoded><![CDATA[<p>So far in the <a href="http://degizmo.com/series-django-tutorials/">tutorial</a> we&#8217;ve <a href="http://degizmo.com/2010/03/15/tutorial-starting-a-project/">started our project</a>, <a href="http://degizmo.com/2010/03/16/tutorial-setting-up-the-database/">setup the database</a>, <a href="http://degizmo.com/2010/03/17/tutorial-the-admin-interface/">enabled the admin interface</a> and now we&#8217;re ready to start to define the database for our project, a simple blog.</p>
<p>This is where we will start working with the models.py file in the &#8220;main&#8221; application directory (blog/main/). The models.py file is a definition file where we tell Django what all of our database models are. Let&#8217;s start with some categories for our blog entry.</p>
<pre class="brush: python;">
from django.db import models
from django.contrib import admin

class Category(models.Model):
    Name    =   models.CharField(max_length=255)
    def __unicode__(self):
        return self.Name
admin.site.register(Category)
</pre>
<p>Let&#8217;s walk through this real quick since this was a lot of code real quickly. The first two lines we are first importing Django&#8217;s base class &#8220;models&#8221;. This is what we&#8217;ll subclass all of our models off of. The next line imports the Django admin object which we will use to include our model in Django&#8217;s admin interface.</p>
<p><span id="more-18"></span></p>
<p>Next we define our model &#8220;Category&#8221; subclasses it from the Django base class models.Model. Then we define a field in our model called &#8220;Name&#8221;. This is the name of a category and we assign name an instance of another subclass of a base Django class called &#8220;CharField&#8221; this is a simple multi-character field with a maximum length of 255 characters. You can find out more about the types of fields in our <a href="http://degizmo.com/blog/2009/03/quick-reference-models/" class="broken_link" >Quick Reference: Models</a> page.</p>
<p>Next we define a function called __unicode__ in our new Category class. This is a special function which tell&#8217;s Django and Python when we want to &#8220;print&#8221; an instance of this class call this function. This function will return the value &#8220;Name&#8221; from the object so that a Category with the name &#8220;Books&#8221; will return &#8220;Books&#8221; when it is printed out.</p>
<p>The next line &#8220;admin.site.register(Category)&#8221; will tell Django to add our new model Category to the admin site.</p>
<p>Let&#8217;s go ahead and see what this little snippet of code does before moving on. From the console let&#8217;s first sync our database again</p>
<pre class="brush: bash;">
$ python manage.py syncdb
Creating table main_category
</pre>
<p>Here we see that Django has created a table in our database called main_category. &#8220;main&#8221; is the name of our application and &#8220;category&#8221; is the name of our class. Let&#8217;s go ahead and run the development server again and just keep it running in the background this time. It will reload automatically when files in your project and application are changed so I won&#8217;t remind you anymore to run the development server past this point in the tutorial</p>
<pre class="brush: bash;">
$ python manage.py runserver
Validating models...
0 errors found

Django version 1.1 alpha 1, using settings 'blog.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
</pre>
<p>Now let&#8217;s go back to the admin interface at <a href="http://127.0.0.1:8000/admin/">http://127.0.0.1:8000/admin/</a> and see our new model in the admin interface.</p>
<p><img title="Admin - Tutorial - Create Category" src="http://degizmo.com/wp-content/uploads/2009/03/picture-12.png" alt="Admin - Tutorial - Create Category" width="590" height="479" /><br />
We can see our new model &#8220;Categorys&#8221; in the application &#8220;Main&#8221; here. Let&#8217;s click on &#8220;Categorys&#8221; (we&#8217;ll fix that in a minute) to see how cool the admin interface is.</p>
<p><img title="Admin-Tutorial-Category" src="http://degizmo.com/wp-content/uploads/2009/03/picture-13.png" alt="Admin-Tutorial-Category" width="619" height="507" /><br />
Let&#8217;s click &#8220;Add category&#8221; in the top right there and create a new category<br />
<img title="Admin-Tutorial-Create-Category" src="http://degizmo.com/wp-content/uploads/2009/03/picture-2.png" alt="Admin-Tutorial-Create-Category" width="619" height="507" /><br />
<img title="Admin-Category-Created-Books" src="http://degizmo.com/wp-content/uploads/2009/03/picture-3.png" alt="Admin-Category-Created-Books" width="619" height="507" /><br />
Now click on our newly created Category &#8220;Books&#8221; and check out what the Django Admin interface has done for us.<br />
<img title="Admin-Edit-Category-Books" src="http://degizmo.com/wp-content/uploads/2009/03/picture-4.png" alt="Admin-Edit-Category-Books" width="619" height="507" /><br />
All we&#8217;ve done is defined our model and Django has given us a nice CRUD (Create, Edit, Update, Delete) interface for all of data. The admin interface is actually very powerful tool just by itself and anyone who&#8217;s developed web applications knows that doing something like for any project takes a huge amount of time. The admin interface is a massive time saver for any project.</p>
<p>Let&#8217;s go ahead and fix that &#8220;Categorys&#8221; typo before we define another model. Let&#8217;s look at our models.py file again and add a &#8220;Meta&#8221; option to our Category class.</p>
<pre class="brush: python;">
class Category(models.Model):
    Name    =   models.CharField(max_length=255)
    def __unicode__(self):
        return self.Name
    class Meta:
        verbose_name_plural = &quot;Categories&quot;
admin.site.register(Category)
</pre>
<p>If the change isn&#8217;t that self-explanatory we&#8217;ve set the value of verbose_name_plural to the correct plural spelling for &#8220;Category&#8221;. Django will automatically pluralize models but, sometimes it&#8217;s not perfect. It already does so much for us let&#8217;s not complain about the small things.</p>
<p>Now let&#8217;s define our second model. This is for our blog posts.</p>
<pre class="brush: python;">
from django.contrib.auth.models import User
class BlogPost(models.Model):
	Title		= models.CharField(max_length=255)
	Category	= models.ForeignKey(Category)
	Slug		= models.SlugField()
	Author		= models.ForeignKey(User)
	PostText	= models.TextField()
	PublishDate	= models.DateTimeField(auto_now_add=True)
	def __unicode__(self):
	    return self.Title
admin.site.register(BlogPost)
</pre>
<p>So we should be able to look at this code and begin to figure out what some of it does. The &#8220;Title&#8221; field is almost identical to our Category -&gt; Name field but, the ForeignKey field is new and worth an explanation. Here we are defining the relationship between a BlogPost and a Category by saying that every BlogPost belongs in some Category. Then we have &#8220;SlugField&#8221; which is new too. A slug is the URL of a blog post, for example the slug of this blog post is &#8220;blog/2010/03/tutorial-create-our-models/&#8221;.</p>
<p>Next we have another ForeignKey but, it&#8217;s something we haven&#8217;t declared. I skipped over the first line in our code up there at first to explain it a bit more in detail here. We imported &#8220;from django.contrib.auth.models import User&#8221;. This is the &#8220;User&#8221; class that Django uses. Everyone on our website: admins, authors, commenter, even anonymous users are &#8220;Users&#8221;. In this line we are saying that every BlogPost has a single author &#8220;User&#8221;.</p>
<p>Hopefully PostText is self-explanatory so we&#8217;ll skip to PublishDate. This is a DateTimeField which not surprisingly stores a Date and a Time. The snippet in the paren&#8217;s &#8220;auto_now_add=True&#8221; means that when the model (the BlogPost) is created the date and time are automatically added instead of being defined by someone.</p>
<p>Let&#8217;s resync our database and go back to the admin screen and see what we have now</p>
<p><img title="Admin-BlogPosts" src="http://degizmo.com/wp-content/uploads/2009/03/picture-5.png" alt="Admin-BlogPosts" width="619" height="507" /><br />
We see our model &#8220;Blog posts&#8221; included in our admin. Let&#8217;s go into that and write a blog post.</p>
<p><img title="Admin-Create-BlogPost" src="http://degizmo.com/wp-content/uploads/2009/03/picture-6.png" alt="Admin-Create-BlogPost" width="619" height="507" /><br />
You can see how Django is handling the relationships you&#8217;ve defined in your models so far with the &#8220;Categories&#8221; and &#8220;Author&#8221; drop downs. Pretty cool huh? This is the real power of the admin interface in Django. It provides a ready made very powerful interface for your database out of the box with very little configuration needed. This admin interface is actually much more powerful that what we&#8217;ve covered here.</p>
<p>Go ahead and create another Category and one or two Blog Posts just to get some data into the database for the <a href="http://degizmo.com/2010/03/20/tutorial-learning-the-db-api-and-orm/">next part of the tutorial</a>. There we&#8217;ll learn about the DB-API and the ORM in Django.</p>
<h3>Download at this step: <a href="http://github.com/degizmo/django-tutorial/zipball/9b4ed7bd17bb89d7c5eaec5c6650ce8195df69d0">GitHub</a></h3>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/flIwX39VW6A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/03/18/tutorial-create-our-models/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/03/18/tutorial-create-our-models/</feedburner:origLink></item>
		<item>
		<title>Tutorial: The Admin Interface</title>
		<link>http://feedproxy.google.com/~r/degizmo_blog/~3/QFJ7Yznth-4/</link>
		<comments>http://degizmo.com/2010/03/17/tutorial-the-admin-interface/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 02:31:54 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://degizmo.com/?p=17</guid>
		<description><![CDATA[So we&#8217;ve setup our application, initilized our database and now we&#8217;re ready to take our first look at one of the cooler features in Django, the admin interface.
Let&#8217;s open up the urls.py file in the root project (blog/) directory. I&#8217;ve removed the some of the commented out lines below for brevity

from django.conf.urls.defaults import *

# Uncomment the next [...]]]></description>
			<content:encoded><![CDATA[<p>So we&#8217;ve <a href="http://degizmo.com/2010/03/15/tutorial-starting-a-project/">setup our application</a>, <a href="http://degizmo.com/2010/03/16/tutorial-setting-up-the-database/">initilized our database</a> and now we&#8217;re ready to take our first look at one of the cooler features in Django, the admin interface.</p>
<p>Let&#8217;s open up the urls.py file in the root project (blog/) directory. I&#8217;ve removed the some of the commented out lines below for brevity</p>
<pre class="brush: python;">
from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',

    # Uncomment the next line to enable the admin:
    # (r'^admin/', include(admin.site.urls)),
)&lt;
</pre>
<p><span id="more-17"></span><br />
Now just like the comments say we want to uncomment out the &#8220;from django.contrib&#8230;&#8221;, &#8220;admin.autodiscover()&#8221;, and the &#8220;(r^admin/&#8230;)&#8221; lines in urls.py so it looks like this</p>
<pre class="brush: python;">
from django.conf.urls.defaults import *
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',
 (r'^admin/', include(admin.site.urls)),
)
</pre>
<p>Now, what does all of this do? The first two lines (the imports) are bringing in the needed modules and the admin. namespace for us. The urlspatterns line is something we&#8217;ll be coming back to. A simple explination of it is that this is where all the URL&#8217;s of our project will end up living. Right now there is one URL &#8220;admin/&#8221; that is pointing to another URL file &#8220;admin.site.urls&#8221;. This is the base URL&#8217;s of the Django admin site.</p>
<p>After we&#8217;ve saved our changes let&#8217;s run the development server again</p>
<pre class="brush: python;">
$ python manage.py runserver
Validating models...
0 errors found

Django version 1.1 alpha 1, using settings 'blog.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
</pre>
<p>This time let&#8217;s goto the URL <a href="http://127.0.0.1:8000/admin">http://127.0.0.1:8000/admin/</a></p>
<p><img title="Admin-Login" src="http://degizmo.com/wp-content/uploads/2009/03/picture-1.png" alt="Admin-Login" width="600" height="491" /></p>
<p>Well, now we&#8217;re getting somewhere. Log in with the superuser account that you created in <a href="http://degizmo.com/2010/03/16/tutorial-setting-up-the-database/">step 3</a></p>
<p><img title="Admin-Main" src="http://degizmo.com/wp-content/uploads/2009/03/picture-11.png" alt="Admin-Main" width="619" height="507" /></p>
<p>Go ahead poke around for a few minutes. Check out the users section. Create a new user! Create a group, check out the permissions. This all came from adding one line of code to your INSTALLED_APPS. Pretty cool huh? You smiling yet?</p>
<p>This admin screen isn&#8217;t just for Django created stuff like users and groups. This is where your data will eventually live too. So let&#8217;s go ahead to the <a href="http://degizmo.com/2010/03/18/tutorial-create-our-models/">next step and create some models for our blog application.</a></p>
<h3>Download at this step: <a href="http://github.com/degizmo/django-tutorial/zipball/cc1071dcfd8b38a383d9d16ff7a817952e634e88">GitHub</a></h3>
<img src="http://feeds.feedburner.com/~r/degizmo_blog/~4/QFJ7Yznth-4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://degizmo.com/2010/03/17/tutorial-the-admin-interface/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://degizmo.com/2010/03/17/tutorial-the-admin-interface/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 2.211 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-05-26 14:18:11 -->
