<?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>chris moos&#039;s blog &#187; django</title>
	<atom:link href="http://chrismoos.com/category/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://chrismoos.com</link>
	<description>coding my way through life</description>
	<lastBuildDate>Sun, 18 Sep 2011 19:48:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>CouchDB and Pylons: User Registration and&#160;Login</title>
		<link>http://chrismoos.com/2009/02/21/couchdb-and-pylons-user-registration-and-login/</link>
		<comments>http://chrismoos.com/2009/02/21/couchdb-and-pylons-user-registration-and-login/#comments</comments>
		<pubDate>Sun, 22 Feb 2009 01:47:08 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[formencode]]></category>
		<category><![CDATA[pylons]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=200</guid>
		<description><![CDATA[In the previous tutorial, we learned how to get CouchDB and Pylons up and running, as well as create a simple page counter. Now we are going to implement a simple user authentication system. This tutorial will teach you how to use formencode to validate forms and CouchDB to store our user data. Let&#8217;s start [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://chrismoos.com/2009/02/03/couchdb-and-pylons-getting-started/">previous tutorial</a>, we learned how to get CouchDB and Pylons up and running, as well as create a simple page counter. Now we are going to implement a simple user authentication system. This tutorial will teach you how to use <a href="http://www.formencode.org/">formencode</a> to validate forms and CouchDB to store our user data.</p>
<p>Let&#8217;s start by creating a new pylons project and some controllers.</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ paster create <span style="color: #660033;">-t</span> pylons userdemo<br />
$ <span style="color: #7a0874; font-weight: bold;">cd</span> userdemo<br />
$ paster controller main<br />
$ paster controller auth</div></td></tr></tbody></table></div>
<p>Also, delete public/index.html.</p>
<p>For our controller main, we are going to add one action called <em>index</em>. This will be the main page for the site and will only be accessible for logged in users. If a user is not logged in, they will be redirected to the login page. Let&#8217;s add some routes for the main page, login, logout, and registration. Open up config/routing.py.</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #008000;">map</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span><span style="color: #66cc66;">,</span> controller<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'main'</span><span style="color: #66cc66;">,</span> action<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'index'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">map</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/auth/login'</span><span style="color: #66cc66;">,</span> controller<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'auth'</span><span style="color: #66cc66;">,</span> action<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'login'</span><span style="color: #66cc66;">,</span> conditions<span style="color: #66cc66;">=</span><span style="color: #008000;">dict</span><span style="color: black;">&#40;</span>method<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'GET'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">map</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/auth/login'</span><span style="color: #66cc66;">,</span> controller<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'auth'</span><span style="color: #66cc66;">,</span> action<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'login_post'</span><span style="color: #66cc66;">,</span> conditions<span style="color: #66cc66;">=</span><span style="color: #008000;">dict</span><span style="color: black;">&#40;</span>method<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'POST'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">map</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/auth/logout'</span><span style="color: #66cc66;">,</span> controller<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'auth'</span><span style="color: #66cc66;">,</span> action<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'logout'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">map</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/auth/register'</span><span style="color: #66cc66;">,</span> controller<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'auth'</span><span style="color: #66cc66;">,</span> action<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'register'</span><span style="color: #66cc66;">,</span> conditions<span style="color: #66cc66;">=</span><span style="color: #008000;">dict</span><span style="color: black;">&#40;</span>method<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'GET'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">map</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/auth/register'</span><span style="color: #66cc66;">,</span> controller<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'auth'</span><span style="color: #66cc66;">,</span> action<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'register_post'</span><span style="color: #66cc66;">,</span> conditions<span style="color: #66cc66;">=</span><span style="color: #008000;">dict</span><span style="color: black;">&#40;</span>method<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'POST'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>For checking to see if a user is logged in, we will store a <em>user_id</em> in the session. Let&#8217;s make a decorator that we can add to our index action that will check to see if a user is logged in. If the user isn&#8217;t logged in, it will redirect to the login page. Your <em>controllers/main.py</em> should look have this:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> decorator <span style="color: #ff7700;font-weight:bold;">import</span> decorator<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> require_login<span style="color: black;">&#40;</span>func<span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot; Checks to see if user_id is in session &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #483d8b;">'user_id'</span> <span style="color: #ff7700;font-weight:bold;">in</span> session:<br />
&nbsp; &nbsp; &nbsp; &nbsp; redirect_to<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/auth/login'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> func<span style="color: black;">&#40;</span>*args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span><br />
require_login <span style="color: #66cc66;">=</span> decorator<span style="color: black;">&#40;</span>require_login<span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> MainController<span style="color: black;">&#40;</span>BaseController<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #66cc66;">@</span>require_login<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> index<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'You are logged in! Click &lt;a href=&quot;/auth/logout&quot;&gt;here&lt;/a&gt; to logout.'</span></div></td></tr></tbody></table></div>
<p><span id="more-200"></span></p>
<p>If you start the server now and go to <a href="http://localhost:5000">http://localhost:5000</a> you will be redirected to /auth/login. Good. Let&#8217;s get into CouchDB now&#8230;</p>
<p>Open up <a href="http://localhost:5984/_utils">http://localhost:5984/_utils</a> and create a new database, and call it <em>userdemo</em>.</p>
<p>Now we are going to define our User schema in <em>model/__init__.py</em>. A schema describes a certain type of document, and in this case, it will be a User document. This example is very simple, so we only need username, password, and salt. Note the other field, <em>type</em>. This will specify that the document is for users, and it will be automatically set with the default parameter when we store a document. We are also going to create a simple helper function that will return an instance of our database(from couchdb-python).</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> couchdb <span style="color: #ff7700;font-weight:bold;">import</span> Server<br />
<span style="color: #ff7700;font-weight:bold;">from</span> couchdb <span style="color: #ff7700;font-weight:bold;">import</span> schema<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> get_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; server <span style="color: #66cc66;">=</span> Server<span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://localhost:5984/'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> server<span style="color: black;">&#91;</span><span style="color: #483d8b;">'userdemo'</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; <br />
<span style="color: #ff7700;font-weight:bold;">class</span> User<span style="color: black;">&#40;</span>schema.<span style="color: black;">Document</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot; Simple user document &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; username <span style="color: #66cc66;">=</span> schema.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; password <span style="color: #66cc66;">=</span> schema.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; salt <span style="color: #66cc66;">=</span> schema.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">type</span> <span style="color: #66cc66;">=</span> schema.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span>default<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'user'</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>Next, we are going to create a simple template for auth/login. This will prompt the user to login, or register if the user does not have an account. (I assume you are using <a href="http://www.makotemplates.org/">mako</a> for your template engine).</p>
<p><em>templates/login.mak</em>:</p>
<div class="codecolorer-container xml blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;head<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Login<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;h1<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Login<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/h1<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;form</span> <span style="color: #000066;">action</span>=<span style="color: #ff0000;">&quot;/auth/login&quot;</span> <span style="color: #000066;">method</span>=<span style="color: #ff0000;">&quot;post&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;table<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tr<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;th<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Username:<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/th<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;td<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${h.text('username')}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/td<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/tr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tr<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;th<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Password:<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/th<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;td<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${h.password('password')}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/td<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/tr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/table<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;Login&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/form<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
% if c.invalid_user:<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>*** An invalid username or password was entered.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
% endif<br />
<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Don't have an account? Click <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;/auth/register&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>here<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> to register.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/body<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
<p>Notice that we used h.text() and h.password(). These helpers create our input boxes and will also display an error when we get into form validation. Make sure to import those functions in <em>lib/helpers.py</em>.</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> webhelpers.<span style="color: black;">html</span>.<span style="color: black;">tags</span> <span style="color: #ff7700;font-weight:bold;">import</span> text<span style="color: #66cc66;">,</span> password</div></td></tr></tbody></table></div>
<p>Now that we&#8217;ve created or login template, let&#8217;s implement our action auth/login in <em>controllers/auth.py</em>.</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> AuthController<span style="color: black;">&#40;</span>BaseController<span style="color: black;">&#41;</span>:<br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> login<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> render<span style="color: black;">&#40;</span><span style="color: #483d8b;">'login.mak'</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>Okay, let&#8217;s run the server and try to go to <a href="http://localhost:5000">http://localhost:5000</a>. We are redirect to our new login page.</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>paster serve <span style="color: #660033;">--reload</span> development.ini</div></td></tr></tbody></table></div>
<p><img src="http://cdn.chrismoos.com/wp-content/uploads/2009/02/login.png" /></p>
<p>Okay, now let&#8217;s implement our login action. This is under <em>controllers/auth.py</em>, and the action is login_post. The first thing we will do is add a formencode schema for our login form. This will make sure the username and/or password is not empty, and it will display an error accordingly. Here is what our new auth.py file might look like.</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> formencode<br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> LoginForm<span style="color: black;">&#40;</span>formencode.<span style="color: black;">Schema</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; username <span style="color: #66cc66;">=</span> formencode.<span style="color: black;">validators</span>.<span style="color: black;">String</span><span style="color: black;">&#40;</span>not_empty<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; password <span style="color: #66cc66;">=</span> formencode.<span style="color: black;">validators</span>.<span style="color: black;">String</span><span style="color: black;">&#40;</span>not_empty<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> AuthController<span style="color: black;">&#40;</span>BaseController<span style="color: black;">&#41;</span>:<br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> login<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> render<span style="color: black;">&#40;</span><span style="color: #483d8b;">'login.mak'</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> AuthController<span style="color: black;">&#40;</span>BaseController<span style="color: black;">&#41;</span>:<br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> login<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> render<span style="color: black;">&#40;</span><span style="color: #483d8b;">'login.mak'</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> login_post<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; form_result <span style="color: #66cc66;">=</span> LoginForm<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">to_python</span><span style="color: black;">&#40;</span>request.<span style="color: black;">POST</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">user</span> <span style="color: #66cc66;">=</span> authenticate_user<span style="color: black;">&#40;</span>form_result<span style="color: black;">&#91;</span><span style="color: #483d8b;">'username'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> form_result<span style="color: black;">&#91;</span><span style="color: #483d8b;">'password'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; session<span style="color: black;">&#91;</span><span style="color: #483d8b;">'user_id'</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">user</span>.<span style="color: #008000;">id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; session.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; redirect_to<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> InvalidUser:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c.<span style="color: black;">invalid_user</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> render<span style="color: black;">&#40;</span><span style="color: #483d8b;">'login.mak'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> formencode.<span style="color: black;">Invalid</span><span style="color: #66cc66;">,</span> err:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; html <span style="color: #66cc66;">=</span> render<span style="color: black;">&#40;</span><span style="color: #483d8b;">'login.mak'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> formencode.<span style="color: black;">htmlfill</span>.<span style="color: black;">render</span><span style="color: black;">&#40;</span>html<span style="color: #66cc66;">,</span> errors<span style="color: #66cc66;">=</span>err.<span style="color: black;">error_dict</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>This login_post action first checks to see if the form is valid, if not, it will display the login form with the appropriate errors. If the form is valid, we attempt to call the function <em>authenticate_user</em>, which will return a valid User document if the login is successful, or raise an Exception if the login information is invalid. If the login is valid, we save the user.id in our session. If not, we set the invalid_user context variable and return the login page.</p>
<p>Okay, so we have our login_post action defined, but we don&#8217;t have an authenticate_user method yet. Let&#8217;s implement that. But before we do that, we need to know a little bit more about <a href="http://wiki.apache.org/couchdb/HTTP_view_API">CouchDB views</a>. A view is a way to query data from our database. A view is defined by implementing map and reduce functions. </p>
<p>Let&#8217;s start by adding a user view, that will let us query user data. To create the view, go to <a href="http://localhost:5984/_utils">http://localhost:5984/_utils</a> and select the userdemo database. Go to <em>Create Document</em>. We are going to create a <em>design document</em> which is where the views are defined. The document ID should be <em>_design/user</em>. This view is accessible via http://localhost:5984/userdemo/_view/user/VIEW_FUNC. To define our view functions, open the newly created _design/user document and add a field called <em>views</em>. For now, just put <em>{}</em> for the value. Hit save document. </p>
<p>Each view function defines a map and optionally a reduce function. This lets us limit and control what documents our view will return. For now, we just want a simple view that allows us to query the database and get a user by the username. Remember that CouchDB returns data with a key/value. The key we want to return is the username. </p>
<p>Let&#8217;s talk about <em>map</em> for a second. A map function is passed a CouchDB document, and then <em>emits</em>, or adds, key/value pairs. CouchDB uses javascript as the default view server. We will call our view function <em>by_username</em>, and it will return the username as the key and the user document as the value. Open your _design/user document and put this in for the views field.</p>
<div class="codecolorer-container javascript blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">&quot;by_username&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;map&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;function(doc) { if(doc.type == 'user') emit(doc.username, doc); }&quot;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>CouchDB should look like this:<br />
<img src="http://cdn.chrismoos.com/wp-content/uploads/2009/02/couchdb.png"/></p>
<p>Notice that we check doc.type. This is because all documents are stored under one namespace, so we need a way to differentiate between different documents. We do this by setting a type field for every user, with the value &#8220;user&#8221;. You can access this view by going here: <a href="http://localhost:5984/userdemo/_view/user/by_username">http://localhost:5984/userdemo/_view/user/by_username</a>. </p>
<p>Alright, now that we have our view defined, let&#8217;s implement the authenticate_user function. We also create a custom exception class that we use for an invalid user. We use hashlib to generate a sha256 hash of the user&#8217;s password and a random salt. <em>gen_hash_password</em> is used later for our registration functions, for creating a new salt and getting a hash. Add this above your controller in <em>controllers/auth.py</em>.</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> userdemo.<span style="color: black;">model</span> <span style="color: #ff7700;font-weight:bold;">import</span> get_db<span style="color: #66cc66;">,</span> User<br />
<span style="color: #ff7700;font-weight:bold;">import</span> hashlib<br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> InvalidUser<span style="color: black;">&#40;</span><span style="color: #008000;">Exception</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">pass</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> hash_password<span style="color: black;">&#40;</span>password<span style="color: #66cc66;">,</span> salt<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; m <span style="color: #66cc66;">=</span> hashlib.<span style="color: black;">sha256</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; m.<span style="color: black;">update</span><span style="color: black;">&#40;</span>password<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; m.<span style="color: black;">update</span><span style="color: black;">&#40;</span>salt<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> m.<span style="color: black;">hexdigest</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> gen_hash_password<span style="color: black;">&#40;</span>password<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">random</span><br />
&nbsp; &nbsp; letters <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'abcdefghijklmnopqrstuvwxyz0123456789'</span><br />
&nbsp; &nbsp; p <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">''</span><br />
&nbsp; &nbsp; <span style="color: #dc143c;">random</span>.<span style="color: black;">seed</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">32</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; p +<span style="color: #66cc66;">=</span> letters<span style="color: black;">&#91;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>letters<span style="color: black;">&#41;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> hash_password<span style="color: black;">&#40;</span>password<span style="color: #66cc66;">,</span> p<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> p<br />
&nbsp; &nbsp; <br />
<span style="color: #ff7700;font-weight:bold;">def</span> authenticate_user<span style="color: black;">&#40;</span>username<span style="color: #66cc66;">,</span> password<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; result <span style="color: #66cc66;">=</span> User.<span style="color: black;">view</span><span style="color: black;">&#40;</span>get_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'_view/user/by_username'</span><span style="color: #66cc66;">,</span> key<span style="color: #66cc66;">=</span>username<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>result<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">raise</span> InvalidUser<span style="color: black;">&#40;</span><span style="color: #483d8b;">'bad username'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #dc143c;">user</span> <span style="color: #66cc66;">=</span> result.<span style="color: #0000cd;">__iter__</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">next</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># check password</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> hash_password<span style="color: black;">&#40;</span>password<span style="color: #66cc66;">,</span> <span style="color: #dc143c;">user</span>.<span style="color: black;">salt</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #dc143c;">user</span>.<span style="color: black;">password</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">raise</span> InvalidUser<span style="color: black;">&#40;</span><span style="color: #483d8b;">'bad password'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">user</span></div></td></tr></tbody></table></div>
<p>Okay, now our site can login a user. Let&#8217;s get into registration. Create the following functions for our registration action in <em>controllers/auth.py</em>.</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> register<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> render<span style="color: black;">&#40;</span><span style="color: #483d8b;">'register.mak'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> register_post<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; form_result <span style="color: #66cc66;">=</span> RegisterForm<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">to_python</span><span style="color: black;">&#40;</span>request.<span style="color: black;">POST</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">user</span> <span style="color: #66cc66;">=</span> User<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">user</span>.<span style="color: black;">username</span> <span style="color: #66cc66;">=</span> form_result<span style="color: black;">&#91;</span><span style="color: #483d8b;">'username'</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">pwd</span><span style="color: #66cc66;">,</span> salt <span style="color: #66cc66;">=</span> gen_hash_password<span style="color: black;">&#40;</span>form_result<span style="color: black;">&#91;</span><span style="color: #483d8b;">'password'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">user</span>.<span style="color: black;">password</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">pwd</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">user</span>.<span style="color: black;">salt</span> <span style="color: #66cc66;">=</span> salt<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">user</span>.<span style="color: black;">store</span><span style="color: black;">&#40;</span>get_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'You are registered. Click &lt;a href=&quot;/auth/login&quot;&gt;here&lt;/a&gt; to login.'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> formencode.<span style="color: black;">Invalid</span><span style="color: #66cc66;">,</span> err:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; html <span style="color: #66cc66;">=</span> render<span style="color: black;">&#40;</span><span style="color: #483d8b;">'register.mak'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> formencode.<span style="color: black;">htmlfill</span>.<span style="color: black;">render</span><span style="color: black;">&#40;</span>html<span style="color: #66cc66;">,</span> errors<span style="color: #66cc66;">=</span>err.<span style="color: black;">error_dict</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>These functions are similar to the login ones, except here we store a new user into the database, using the User schema document class that we defined in <em>model/__init__.py</em>. We also need to implement the RegisterForm, and also a custom validator, which checks to see if a username is taken.</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> user_exists<span style="color: black;">&#40;</span>username<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; result <span style="color: #66cc66;">=</span> User.<span style="color: black;">view</span><span style="color: black;">&#40;</span>get_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'_view/user/by_username'</span><span style="color: #66cc66;">,</span> key<span style="color: #66cc66;">=</span>username<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>result<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span><br />
&nbsp; &nbsp; <br />
<span style="color: #ff7700;font-weight:bold;">class</span> UsernameValidator<span style="color: black;">&#40;</span>formencode.<span style="color: black;">validators</span>.<span style="color: black;">String</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> validate_python<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> value<span style="color: #66cc66;">,</span> state<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> user_exists<span style="color: black;">&#40;</span>value<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">raise</span> formencode.<span style="color: black;">Invalid</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Username already taken'</span><span style="color: #66cc66;">,</span> value<span style="color: #66cc66;">,</span> state<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
<span style="color: #ff7700;font-weight:bold;">class</span> RegisterForm<span style="color: black;">&#40;</span>formencode.<span style="color: black;">Schema</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; username <span style="color: #66cc66;">=</span> UsernameValidator<span style="color: black;">&#40;</span>not_empty<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; password <span style="color: #66cc66;">=</span> formencode.<span style="color: black;">validators</span>.<span style="color: black;">String</span><span style="color: black;">&#40;</span>not_empty<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>And that&#8217;s it! You can now register an account, login, and view the protected page(with the require_login decorator). Now you just need to add require_login to any function that is only for logged in users. In the next tutorial, I will go into some more advanced CouchDB topics and some cool map/reduce views. </p>
<p>You can download the pylons userdemo project <a href="http://cdn.chrismoos.com/wp-content/uploads/2009/02/userdemo.zip">here</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2009/02/21/couchdb-and-pylons-user-registration-and-login/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Python Web Frameworks: 2 Down, 1 to&#160;go</title>
		<link>http://chrismoos.com/2007/10/17/python-web-frameworks-2-down-1-to-go/</link>
		<comments>http://chrismoos.com/2007/10/17/python-web-frameworks-2-down-1-to-go/#comments</comments>
		<pubDate>Wed, 17 Oct 2007 21:45:21 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[genshi]]></category>
		<category><![CDATA[pylons]]></category>
		<category><![CDATA[sqlalchemy]]></category>
		<category><![CDATA[turbogears]]></category>

		<guid isPermaLink="false">http://chrismoos.com/2007/10/17/python-web-frameworks-2-down-1-to-go/</guid>
		<description><![CDATA[On my trial to find the best python web framework(all around), I&#8217;ve just finished learning Pylons and experiencing everything it has to offer. Genshi is amazing and kills any text template engine(Django, Mako). SQLAlchemy is much different than Django&#8217;s ORM and has its advantages and disadvantages. Django&#8217;s ORM feels more natural and is much easier [...]]]></description>
			<content:encoded><![CDATA[<p>On my trial to find the best python web framework(all around), I&#8217;ve just finished learning Pylons and experiencing everything it has to offer. Genshi is amazing and kills any text template engine(Django, Mako). SQLAlchemy is much different than Django&#8217;s ORM and has its advantages and disadvantages. Django&#8217;s ORM feels more natural and is much easier to learn at first. I believe that SQLAlchemy is much more powerful but the learning curve is much bigger. </p>
<p>Django is a great web framework and I think it is perfect for people that want to build news/content sites. Everything in Django works very well together which makes it a one-stop shop. </p>
<p>Pylons is awesome too but compared to Django is lacking in a lot of documentation. You need to look in a lot of different places to learn all the aspects that Pylons has to offer. I will say that Genshi + SQLAlchemy + Pylons + Routes is very very powerful.</p>
<p>I&#8217;m going to be moving on to TurboGears now to see what is has different. I&#8217;ve read that the documentation is more complete but for the most part the components in each framework are pretty much the same(or can be).</p>
<p>Here it goes.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2007/10/17/python-web-frameworks-2-down-1-to-go/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

