<?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>Webmonkey &#187; django</title>
    <atom:link href="http://www.webmonkey.com/tag/django/feed/" rel="self" type="application/rss+xml" />
    <link>http://www.webmonkey.com</link>
    <description>The Web Developer&#039;s Resource</description>
    <lastBuildDate>Fri, 05 Apr 2013 20:20:46 +0000</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <generator>http://wordpress.org/?v=3.4.2</generator>
    
    <item>
        <title>Get Started With Django</title>
        <link>http://www.webmonkey.com/2010/02/get_started_with_django/</link>
        <comments>http://www.webmonkey.com/2010/02/get_started_with_django/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=919</guid>
        		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[Django is a web framework designed to help you build complex web applications simply and quickly. It&#8217;s written in the Python programming language. Django takes it name from the early jazz guitarist Django Reinhardt, a gypsy savant who managed to play dazzling and electrifying runs on his instrument even though two of the fingers on [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>Django is a web framework designed to help you build complex web applications simply and quickly. It&#8217;s written in the Python programming language.

</p><p>Django takes it name from the early jazz guitarist Django Reinhardt, a gypsy savant who managed to play dazzling and electrifying runs on his instrument even though two of the fingers on his left hand were paralyzed in an accident when he was young.

</p><p>Thus, it&#8217;s a fitting name for the framework: Django can do some very complex things with less code and a simpler execution than you&#8217;d expect. It doesn&#8217;t take a heavy hand to build with Django. The framework does the repetitive work for you, allowing you to get a working website up quickly and easily.

</p><p><br />

</p><span id="more-919"></span>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>



<ol>

<li><a href="#Django.27s_DRY_pledge">Django&#8217;s DRY pledge</a></li>

<li><a href="#Background">Background</a></li>

<li><a href="#Why_isn.27t_Django_a_1.0_release.3F">Why isn&#8217;t Django a 1.0 release?</a></li>

<li><a href="#Structural_overview">Structural overview</a></li>



<li><a href="#So_how_does_Django_work.3F">So how does Django work?</a></li>

<li><a href="#Dive_in">Dive in</a></li>

</ol>

</td></tr></tbody></table>



<a name="Django.27s_DRY_pledge"></a><h2> <span class="mw-headline">Django&#8217;s DRY pledge</span></h2>

<p>Django was designed from the ground up to handle two common web developer challenges: intensive deadlines and strict adherence to the <a href="http://c2.com/cgi/wiki?DontRepeatYourself" class="external text" title="http://c2.com/cgi/wiki?DontRepeatYourself" rel="nofollow">Don&#8217;t Repeat Yourself (DRY) principle</a>. DRY sounds exactly like what it is: Why write the same code over and over again?



</p><p>The result is a fast framework, nimble and capable of generating full site mockups in a very short time. Django&#8217;s slogan captures its essence quite nicely: &#8220;The web framework for perfectionists with deadlines.&#8221;

</p><p>But quick doesn&#8217;t mean sloppy. Django comes with a slick built-in section for administering sites. The admin section supports <a href="http://www.djangoproject.com/documentation/cache/" class="external text" title="http://www.djangoproject.com/documentation/cache/" rel="nofollow">a variety of caching options</a> (including Memcached) and a host of other stable, scalable tools.

</p><p>Perhaps the best part about Django is its outstanding documentation. Unlike many open source projects, Django has <a href="http://www.djangoproject.com/documentation/" class="external text" title="http://www.djangoproject.com/documentation/" rel="nofollow">very thorough and readable docs available online</a>. If you have any problems with our tutorials, head over to the Django site for additional reading. Also consider joining the <a href="http://groups.google.com/group/django-users" class="external text" title="http://groups.google.com/group/django-users" rel="nofollow">django-users Google Group</a> which is full of helpful folks who can point you in the right direction if you run into trouble.

</p>

<a name="Background"></a><h2> <span class="mw-headline">Background</span></h2>

<p>Before we dive in, it&#8217;s worth pausing for a moment to understand where Django comes from, which has influenced both what it is and what it is not.

</p><p>Django was developed over a two year period by programmers working for an online news operation, the <a href="http://www2.ljworld.com/" class="external text" title="http://www2.ljworld.com/" rel="nofollow">Lawrence Journal-World Online</a> in Lawrence, Kansas. Eventually, the team realized it had a real framework on its hands and released the code to the public under an open-source BSD license.



</p><p>Once it became a community project, the development took off and Django began to pop up all over the web. For a complete list of Django sites, check out <a href="http://www.djangosites.org/" class="external text" title="http://www.djangosites.org/" rel="nofollow">Django Sites</a>. Notable examples include <a href="http://pownce.com/" class="external text" title="http://pownce.com/" rel="nofollow">Pownce</a>, <a href="http://projects.washingtonpost.com/congress/" class="external text" title="http://projects.washingtonpost.com/congress/" rel="nofollow">The Washington Post</a> and <a href="http://everyblock.net/" class="external text" title="http://everyblock.net/" rel="nofollow">Everyblock</a>.

</p><p>Perhaps the most common misconception about Django is that it&#8217;s a content management system. It&#8217;s not. It&#8217;s a <a href="/2010/02/Get_Started_with_Web_Frameworks" class="external text" title="/2010/02/Get_Started_with_Web_Frameworks" rel="nofollow">web framework</a>. It is a tool in which to build a CMS, like <a href="http://drupal.org/" class="external text" title="http://drupal.org/" rel="nofollow">Drupal</a> or other systems, but not one in itself.

</p><p>Django is designed to work in a slightly modified Model-View-Controller (MVC) pattern. MVC is a software engineering architecture concept describing how a program can change the visual aspect and the business aspect without affecting one another. The original Django developers refer to it as a model, template and view (MTV) framework.



</p><p>However, in Django&#8217;s vision of MVC development, the &#8220;view&#8221; refers to the data presented to user. Mind you, not <i>how</i> data looks, but <i>which data</i>. In other words, <a href="http://www.djangoproject.com/documentation/faq/" class="external text" title="http://www.djangoproject.com/documentation/faq/" rel="nofollow">to quote the Django documentation</a>, &#8220;the view describes which data you see, not how you see it.&#8221;

</p><p>It leaves the &#8220;how&#8221; to an additional element found in Django: the template.

</p>

<a name="Why_isn.27t_Django_a_1.0_release.3F"></a><h2> <span class="mw-headline"> Why isn&#8217;t Django a 1.0 release? </span></h2>

<p><a href="http://www.webmonkey.com/blog/Django_Deemed_Perfect__Goes_1DOT0" class="external text" title="http://www.webmonkey.com/blog/Django_Deemed_Perfect__Goes_1DOT0" rel="nofollow">It is</a>! Django was released as 1.0 on September 3rd, 2008. <a href="http://www.djangoproject.com/weblog/2009/jul/29/1-point-1/" class="external text" title="http://www.djangoproject.com/weblog/2009/jul/29/1-point-1/" rel="nofollow">Django 1.1 was released on July 29, 2009</a>.



</p>

<a name="Structural_overview"></a><h2> <span class="mw-headline">Structural overview</span></h2>

<p>Django was designed to make web development fast and easy &#8212; dare we say, even fun. And by fast, they mean fast. Once you&#8217;re comfortable with Django, it&#8217;s not hard to go from a simple wireframe to a working demo site in an hour or so.

</p><p>For development purposes, Django is entirely self-contained. It includes a command line interface, a web server and everything you need to get up and running without installing anything other than Django.

</p><p>That said, the web server included with Django is not intended to be used in a production environment. The preferred method is to run Django through <code>mod_python</code> or <code>mod_wsgi</code>. Don&#8217;t worry, we&#8217;ll get to <code>mod_python</code> and <code>mod_wsgi</code> in our more advanced tutorial. First, let&#8217;s look at how you might go about building a Django application.



</p><p>As it turns out, building a Django app actually takes much less time than explaining how to build it.

</p><p>Before we start building sites, it&#8217;s worth asking: What do you mean by building a Django app? Django&#8217;s official documentation and many of its built-in tools are set up to create projects, or containers for your whole site. Within projects you have many apps, or sections of your site.

</p><p>Apps don&#8217;t need to be in projects, and in many cases it&#8217;s better not to put them there.

</p><p>For the sake of example, here&#8217;s a very high-level overview of how a Django app is built:

</p><p>First, create a project using the built in command line tool (<code>python django-admin.py startproject projectname</code>). This will generate a new folder containing the project&#8217;s base settings file which you can use to specify database connections, template locations and more. Also in the folder is urls.py, which defines your base URLs and manage.py, which contains a standard set of command line tools.

</p><p>Next, create an app using the built in command line tool <code>python manage.py startapp appname</code>.

</p><p>Once the app folder is in place, look inside. You&#8217;ll see three files: <code>models.py</code>, <code>urls.py</code> and <code>views.py</code>. These are the files you&#8217;ll use to actually build the app:



</p>

<ul><li> <code>models.py</code> to design your model

</li><li> <code>urls.py</code> to write your URLs

</li><li> <code>views.py</code> to create your views

</li></ul>

<p>Django includes its own template language, but as with many elements of Django, using it entirely optional. You can drop in another template language if you like, but you might want to give Django&#8217;s a try first. It&#8217;s simple and fast, and it&#8217;s already there.

</p><p>The other thing to keep in mind is that Django is written in Python and requires Python 2.3 or higher. Mac OS X and most Linux distros ship with Python 2.5, so you shouldn&#8217;t have any problems. Windows users, however, may need to <a href="http://www.lehuen.com/nicolas/index.php/2005/02/21/39-win32-build-of-mod_python-314-for-python-24" class="external text" title="http://www.lehuen.com/nicolas/index.php/2005/02/21/39-win32-build-of-mod_python-314-for-python-24" rel="nofollow">install Python</a> separately.



</p>

<a name="So_how_does_Django_work.3F"></a><h2> <span class="mw-headline">So how does Django work?</span></h2>

<p>The simplest way to look at Django is to break it down into its component parts. First off, there&#8217;s a <code>models.py</code> file which defines your data model by extrapolating your single lines of code into full database tables and adding a pre-built (totally optional) administration section to manage content.

</p><p>The next element is the <code>urls.py</code> file which uses regular expressions to capture URL patterns for processing.

</p><p>The actual processing happens in your views which, if you haven&#8217;t seen the pattern yet, live in <code>views.py</code>. This is really the meat of Django, since views are where you grab the data you&#8217;re presenting to the visitor.

</p><p>Here&#8217;s what happens when a visitor lands on your Django page:

</p><p><b>1.</b> First, Django consults the various URL patterns you&#8217;ve created and uses the information to retrieve a view.



</p><p><b>2.</b> The view then processes the request, querying your database if necessary.

</p><p><b>3.</b> The view passes the requested information on to your template.

</p><p><b>4.</b> The template then renders the data in a layout you&#8217;ve created and displays the page.

</p><p><br />

</p>

<a name="Dive_in"></a><h2> <span class="mw-headline">Dive in</span></h2>

<p>Now you have at least some idea of how Django works, you&#8217;re ready to dive in and get your hands dirty. It&#8217;s really the best way to learn. For the sake of example, we&#8217;ll be building a blog-type site. It makes a nice intro to Django and takes advantage of some of Django&#8217;s handy shortcuts and other features.

</p><p>We aren&#8217;t going to just build a blog, we&#8217;ll also walk through adding a contact form, static pages (like an &#8220;about&#8221; page) and even integrate it with <a href="http://del.icio.us" class="external text" title="http://del.icio.us" rel="nofollow">del.icio.us</a> web services to display all your del.icio.us bookmarks on your new Django blog.



</p><p>So head on over to part two of our Django series, <a href="/2010/02/Install_Django_and_Build_Your_First_App" title="Tutorial:Install Django and Build Your First App">Install Django and Build Your First App</a>

</p>

<div id="series">

<div class="series_hdr">From the Django Tutorial series</div>

<table style="background: rgb(229, 249, 255) none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" width="620">

<tbody><tr>

<td>

<p><strong class="selflink"> Lesson 1: Get Started With Django</strong><br />

<a href="/2010/02/Install_Django_and_Build_Your_First_App" title="Tutorial:Install Django and Build Your First App"> Lesson 2: Install Django and Build Your First App</a><br />

<a href="/2010/02/Use_URL_Patterns_and_Views_in_Django" title="Tutorial:Use URL Patterns and Views in Django"> Lesson 3: Use URL Patterns and Views in Django</a><br />



<a href="/2010/02/Use_Templates_in_Django" title="Tutorial:Use Templates in Django"> Lesson 4: User Templates in Django</a><br />

<a href="/2010/02/Integrate_Web_APIs_into_Your_Django_Site" title="Tutorial:Integrate Web APIs into Your Django Site"> Lesson 5: Use Web API Data in Django</a><br />

<a href="/2010/02/Build_a_Microblog_with_Django" title="Tutorial:Build a Microblog with Django"> Lesson 6: Build a Microblog with Django</a>

</p>

</td></tr></tbody></table>

</div><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/get_started_with_django/feed/</wfw:commentRss>
        <slash:comments>8</slash:comments>

        
    </item>
    
    <item>
        <title>Install Django and Build Your First App</title>
        <link>http://www.webmonkey.com/2010/02/install_django_and_build_your_first_app/</link>
        <comments>http://www.webmonkey.com/2010/02/install_django_and_build_your_first_app/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=921</guid>
        		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[In our Introduction to Django, we covered all the basics of using the open source web-building framework. If you haven&#8217;t read through our beginner&#8217;s tutorial, go ahead and do so now. If you&#8217;ve already made it through the easy stuff, you&#8217;re probably ready to dive into some code and start building &#8212; so let&#8217;s do [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>In our <a href="/2010/02/Get_Started_With_Django" title="Tutorial:Get Started With Django">Introduction to Django</a>, we covered all the basics of using the open source web-building framework. If you haven&#8217;t read through our beginner&#8217;s tutorial, go ahead and do so now. If you&#8217;ve already made it through the easy stuff, you&#8217;re probably ready to dive into some code and start building &#8212; so let&#8217;s do it.

</p><p>Our first step is to grab a copy of Django and set up a development environment where we can tinker away.
<br />

<span id="more-921"></span>

</p>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>

<ol>



<li><a href="#Install_Django">Install Django</a></li>

<li><a href="#Set_up_your_first_project">Set up your first project</a></li>

<li><a href="#Fill_out_the_project_settings">Fill out the project settings</a></li>

<li><a href="#Set_up_a_user">Set up a user</a></li>

<li><a href="#Start_the_server">Start the server</a></li>



<li><a href="#Build_the_blog">Build the blog</a></li>

<li><a href="#Check_your_head">Check your head</a></li>

<li><a href="#Tweak_the_links_and_tags">Tweak the links and tags</a></li>

<li><a href="#Onward_and_upward">Onward and upward</a></li>

</ol>



</td></tr></tbody></table>


<a name="Install_Django"></a><h2> <span class="mw-headline">Install Django</span></h2>

<p>Django 1.1 was released on July 29th, 2009. You can download the official release <a href="http://www.djangoproject.com/download/" class="external text" title="http://www.djangoproject.com/download/" rel="nofollow">here</a> and follow <a href="http://docs.djangoproject.com/en/dev/topics/install/#installing-official-release" class="external text" title="http://docs.djangoproject.com/en/dev/topics/install/#installing-official-release" rel="nofollow">these instructions</a> for installing.

</p><p>Alternatively, if you want to get the latest and greatest Django tools, you can checkout a copy of the trunk build using Subversion.

</p><p>If you don&#8217;t have <a href="http://subversion.tigris.org/" class="external text" title="http://subversion.tigris.org/" rel="nofollow">Subversion</a> installed, go grab a copy.



</p><p>Then fire up your terminal and paste in this line:

</p>

<pre class="brush: js"> svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk

</pre>

<p>Once all the files finish downloading, we need to make sure our local Python installation is aware that Django exists on our machine. There are a couple ways to go about that, but a symbolic link to your Python site packages directory is probably the easiest.

</p><p>Assuming you&#8217;re on a *nix system, this line will do the trick:

</p>

<pre class="brush: js">ln -s `pwd`/django-trunk/django /path/to/python_site_packages/django

</pre>

<p>If you don&#8217;t know where your Python site directory is, here&#8217;s a handy bit of Python that will tell you:

</p>

<pre class="brush: js">python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"

</pre>

<p>If you&#8217;re on Windows, the easiest thing to do is add Django to your PythonPath environment variable. On Windows, you can define environment variables in the Control Panel. To do this, see Microsoft&#8217;s <a href="http://technet.microsoft.com/en-us/library/bb491071.aspx" class="external text" title="http://technet.microsoft.com/en-us/library/bb491071.aspx" rel="nofollow">Command Line Reference</a> for more details.



</p><p>The excellent and well-written Django <a href="http://www.djangoproject.com/documentation/install/" class="external text" title="http://www.djangoproject.com/documentation/install/" rel="nofollow">installation docs</a> suggest creating a symbolic link to the file <code>django-trunk/django/bin/django-admin.py</code> in a directory on your system path, such as <tt>/usr/local/bin</tt>. I find that I don&#8217;t use <code>django-admin.py</code> all that often, but you can create the link if you like.

</p><p>Just paste this code in your shell:

</p>

<pre class="brush: js">ln -s `pwd`/path/to/django-trunk/django/bin/django-admin.py /usr/local/bin

</pre>

<p>Now that Django is installed and Python knows where it lives, we&#8217;re ready to get started.



</p><p>Remember that you have a Subversion checkout now. If you ever want to update to the latest release, just head to the &#8220;django-trunk&#8221; folder and run <code>svn update</code>.

</p>

<a name="Set_up_your_first_project"></a><h2> <span class="mw-headline">Set up your first project</span></h2>

<p>OK, let&#8217;s get started. From the command line, switch to your web development directory. Something like this:

</p>

<pre class="brush: js">cd ~/sites/dev

</pre>

<p>Now we&#8217;re going to run the <code>django-admin</code> tool we mentioned earlier. If you created the symlink, you don&#8217;t need the full path, but if you didn&#8217;t here&#8217;s the code:

</p>

<pre class="brush: js">python /path/to/django-trunk/django/bin/django-admin.py startproject djangoblog



</pre>

<p>Yep, you read that last bit correctly &#8212; we&#8217;re going to build a blog.

</p><p>Now cd over to the new folder:

</p>

<pre class="brush: js">cd ~/sites/dev/djangoblog

</pre>

<p>This is going to be our project folder into which we will add various apps. Some we&#8217;ll create and some we&#8217;ll be downloading as projects from Google Code. I like to keep my Python import statements clean and free of project-specific module names, so I always make sure my root project folder (in this case, djangoblog) is on my Python path. To do that, just add the path to your <code>PythonPath</code> variable.

</p><p>That way we can write statements like:

</p>

<pre class="brush: js">import myapp

</pre>

<p>rather than

</p>

<pre class="brush: js">import myproject.myapp



</pre>

<p>It&#8217;s not a huge thing, but it does make your code more portable.

</p>

<a name="Fill_out_the_project_settings"></a><h2> <span class="mw-headline">Fill out the project settings</span></h2>

<p>OK, we&#8217;re getting there. The next step is to fill out our project settings file. Fire up your favorite text editor and open up the <code>settings.py</code> file inside the &#8220;djangoblog&#8221; directory.

</p><p>The core of what we need to set up is at the top of the file. Look for these lines:

</p>

<pre class="brush: js">DATABASE_ENGINE = 'sqlite3'  # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.

DATABASE_NAME = '/path/to/djangoblog/djangoblog.db' # Or path to database file if using sqlite3.

DATABASE_USER = ''             # Not used with sqlite3.

DATABASE_PASSWORD = ''         # Not used with sqlite3.

DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.

DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.

</pre>

<p>Note that we&#8217;re using SQLite as a database for development purposes. Assuming you have Python 2.5 installed, you don&#8217;t need to do anything to use SQLite. If you&#8217;re on either Python 2.3 or Python 2.4, you&#8217;ll need <a href="http://oss.itsystementwicklung.de/trac/pysqlite/" class="external text" title="http://oss.itsystementwicklung.de/trac/pysqlite/" rel="nofollow">pysqlite</a> &#8212; make sure you install version 2.0.3 or higher. If you have MySQL or PostgreSQL already installed, feel free to use them.



</p><p>Make Sure to include the entire pathname, as Django cannot understand ~/ or $HOME in defining the database ie /Users/usrname/Sites/dev/djangoblog/djangoblog.db

</p><p>The other settings are well documented in the <code>settings.py</code> file and we can skip over most of them for now. But there are a couple of settings we should take care of before moving on. If you look at the bottom of the <code>settings.py</code> file you&#8217;ll notice this bit of code:

</p>

<pre class="brush: js">INSTALLED_APPS = (

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.sites',

)

</pre>

<p>This where we tell our Django project which apps we want to install. In a minute, we&#8217;ll add our blog app. But for now let&#8217;s just add Django&#8217;s built-in admin tool. Paste in this line just below the sites app:

</p>

<pre class="brush: js">'django.contrib.admin',

</pre>

<p>One more thing before we finish with <code>settings.py</code>, here&#8217;s a handy trick for the template directories. I generally keep all my templates in a folder named &#8220;templates&#8221; within my project folder (in this case, &#8220;djangoblog&#8221;). But I generally move between development and live servers quite a bit and I hate having to change the path to the templates folder. This trick takes care of that:



</p>

<pre class="brush: js">import os.path

TEMPLATE_DIRS = (

	os.path.join(os.path.dirname(__file__), 'templates'),

)

</pre>

<p>Instead of hard coding the path to our templates folder this is dynamic &#8212; and it showcases how easy it is to tweak Django using Python. We just import the <code>os.path</code> Python module and then find the path to the directory where settings.py is and then appends &#8216;templates&#8217; to that path.

</p><p>Now when we push the site live, there&#8217;s no need to change the <code>settings.py</code> file. (Actually you&#8217;d probably want to switch to a more robust database, but we&#8217;ll get to that much later).

</p><p>For now, let&#8217;s use one of the tools included in <code>manage.py</code>, the <code>syncdb</code> tool. Paste this line in your terminal:



</p>

<pre class="brush: js">python manage.py syncdb

</pre>

<p>The <code>syncdb</code> tool tells Django to translate all our installed apps&#8217; <code>models.py</code> files into actual database table. In this case the only thing we have installed are some of the built-in Django tools, but fear not, we&#8217;ll get to writing our own models in just a minute.

</p><p><br />

</p>

<a name="Set_up_a_user"></a><h2> <span class="mw-headline">Set up a user</span></h2>

<p>Once you enter the <code>syncdb</code> line above, you&#8217;ll get some feedback from Django telling you you&#8217;ve just installed the auth system. It will walk you through setting up a user. The output looks like this:



</p>

<pre class="brush: js">sng: /djangoblog/ $ python manage.py syncdb

Creating table auth_message

Creating table auth_group

Creating table auth_user

Creating table auth_permission

Creating table django_content_type

Creating table django_session

Creating table django_site

Creating table django_admin_log



You just installed Django's auth system, which means you don't have any superusers defined.

Would you like to create one now? (yes/no): yes

Username (Leave blank to use 'luxagraf'):

E-mail address: none@none.com

Password:

Password (again):

Superuser created successfully.

Installing index for auth.Message model

Installing index for auth.Permission model

Installing index for admin.LogEntry model

sng: /djangoblog/ $

</pre>

<p>Once you&#8217;ve created your username and password, it&#8217;s time to fire up Django&#8217;s built-in server.

</p>

<a name="Start_the_server"></a><h2> <span class="mw-headline">Start the server</span></h2>

<p>At the command prompt, tell Django to start the server:

</p>

<pre class="brush: js">/djangoblog/ $ python manage.py runserver

Validating models...

0 errors found



Django version 0.97-pre-SVN-6920, using settings 'djangoblog.settings'

Development server is running at http://127.0.0.1:8000/

Quit the server with CONTROL-C.

</pre>

<p>Now open up your browser and head to <a href="http://127.0.0.1:8000/" class="external free" title="http://127.0.0.1:8000/" rel="nofollow">http://127.0.0.1:8000/</a>. You should see a page like this:

</p><p><a href="/special/image/Djangopart2_1.jpg" class="image" title="Image:Djangopart2_1.jpg"><img alt="Image:Djangopart2_1.jpg" src="/mediawiki/images/Djangopart2_1.jpg" border="0" height="185" width="630"></a>

</p><p>It works! But that isn&#8217;t very exciting yet, so let&#8217;s check out the admin interface. However, before we do that, we need to tell Django what the admin URL is.



</p><p>Fire up your text editor and open the file <code>urls.py</code> in your &#8220;djangoblog&#8221; folder. Copy and paste the code below, replacing what&#8217;s already in the file:

</p>

<pre class="brush: js">from django.conf.urls.defaults import *

from django.contrib import admin



# Uncomment the next two lines to enable the admin:

# from django.contrib import admin

admin.autodiscover()



urlpatterns = patterns('',

     (r'^admin/(.*)', admin.site.root),

)



</pre>

<p>Now head to <a href="http://127.0.0.1:8000/admin/" class="external free" title="http://127.0.0.1:8000/admin/" rel="nofollow">http://127.0.0.1:8000/admin/</a>. Log in with the user/pass combo you created earlier and you should see something like this:

</p><p><a href="/special/image/Djangopart2_2.jpg" class="image" title="Image:Djangopart2_2.jpg"><img alt="Image:Djangopart2_2.jpg" src="/mediawiki/images/Djangopart2_2.jpg" border="0" height="210" width="630"></a>

</p><p>Now that&#8217;s pretty cool. If you&#8217;ve ever labored over creating an admin system in Ruby on Rails or PHP, you&#8217;re going to love Django&#8217;s built-in admin system.

</p><p>But at the moment there isn&#8217;t much to see in the admin system, so let&#8217;s get started building our blog.

</p>

<a name="Build_the_blog"></a><h2> <span class="mw-headline">Build the blog</span></h2>



<p>Now we could just throw in some code that creates a date field, title, entry and other basics, but that wouldn&#8217;t be a very complete blog would it? What about tags? An RSS feed? A sitemap? Maybe some <a href="http://daringfireball.net/projects/markdown/" class="external text" title="http://daringfireball.net/projects/markdown/" rel="nofollow">Markdown</a> support for easier publishing?

</p><p>Yeah, let&#8217;s add all that. But remember Django&#8217;s DRY principles &#8212; surely, somebody else has already created a Feed app? A Sitemap app?

</p><p>As a matter of fact Django ships with those built-in.

</p><p>Nice. But what about tags? Well there&#8217;s one of those apps available as well &#8212; the cleverly named <a href="http://code.google.com/p/django-tagging/" class="external text" title="http://code.google.com/p/django-tagging/" rel="nofollow">django-tagging</a>.

</p><p>Now, there have been some backwards-incompatible changes to Django recently, and as of this writing, django-tagging hasn&#8217;t caught up to those yet. So we&#8217;re actually going to need to checkout the Newforms Admin branch of the django-tagging codebase.

</p><p>To do that we&#8217;ll grab the files using Subversion. Paste this code into your terminal window:

</p>

<pre class="brush: js">svn checkout http://django-tagging.googlecode.com/svn/branches/newforms-admin django-tagging

</pre>

<p>Now cd into the new django-tagging folder and type:

</p>

<pre class="brush: js">python setup.py install



</pre>

<p>Then just drop the tagging folder, which you&#8217;ll find inside django-tagging, in your &#8220;djangoblog&#8221; folder or wherever you&#8217;d like to keep it (I use a &#8220;lib&#8221; folder to hold all my frequently used components, like django-tagging).

</p><p>There&#8217;s also a handy <a href="https://sourceforge.net/project/showfiles.php?group_id=153041" class="external text" title="https://sourceforge.net/project/showfiles.php?group_id=153041" rel="nofollow">Python implementation of Markdown</a>, so grab that as well (follow the setup instructions on the site to get Markdown installed). Markdown is entirely optional, so feel free to skip it if it&#8217;s not your thing.

</p><p>Got all that stuff stashed in your &#8220;djangoblog&#8221; folder? Good.

</p><p>Now let&#8217;s go ahead and create our first Django application.

</p><p>To do that we&#8217;ll use Django&#8217;s app creating script, which lives inside <code>manage.py</code> in our project folder. Paste this line into your shell:

</p>

<pre class="brush: js">python manage.py startapp blog

</pre>

<p>If you look inside &#8220;djangoblog&#8221; you should now see a new &#8220;blog&#8221; folder. Open that up and find the <code>models.py</code> file. Open <code>models.py</code> in your favorite text editor and paste in this code:



</p>

<pre class="brush: js">from django.db import models

from django.contrib.syndication.feeds import Feed

from django.contrib.sitemaps import Sitemap



import markdown

from tagging.fields import TagField

from tagging.models import Tag



# Create your models here.



class Entry(models.Model):

    title = models.CharField(max_length=200)

    slug = models.SlugField(

        unique_for_date='pub_date',

        help_text='Automatically built from the title.'

    )

    body_html = models.TextField(blank=True)

    body_markdown = models.TextField() #note, if you're using Markdown, include this field, otherwise just go with body_html

    pub_date = models.DateTimeField('Date published')

    tags = TagField()

    enable_comments = models.BooleanField(default=True)

    PUB_STATUS = (

        (0, 'Draft'),

        (1, 'Published'),

    )

    status = models.IntegerField(choices=PUB_STATUS, default=0)



    class Meta:

        ordering = ('-pub_date',)

        get_latest_by = 'pub_date'

        verbose_name_plural = 'entries'



    def __unicode__(self):

        return u'%s'&nbsp;%(self.title)



    def get_absolute_url(self):

        return "/%s/%s/"&nbsp;%(self.pub_date.strftime("%Y/%b/%d").lower(), self.slug)



    def save(self):

         self.body_html = markdown.markdown(self.body_markdown, safe_mode = False)

         super(Entry, self).save()

</pre>

<p><br />

Let&#8217;s step through the code line by line and we&#8217;ll talk about what&#8217;s going on.

</p><p>First we import the basic stuff from django, including the model class, the Feed class and the Sitemap class.

</p><p>Then we import the tagging and markdown files we just saved in our project folder.

</p><p>Once we have all the modules we&#8217;re going to use, we can create our blog model. I elected to call it Entry &#8212; you can change that name if you like, but remember to substitute your name everywhere I refer to Entry.

</p><p>Entry extends Django&#8217;s built-in <code>model.Model</code> class, which handles all the basic create read update and delete (CRUD) tasks. In other words, all we have to do is tell Django about the various elements of the database table (like the title field, the entry slug, <i>et cetera</i>) and all the hard work is handled behind the scenes.

</p><p>The first bit of our Entry class definition just defines all our various blog entry components. Django will use this information to create our database tables and structure, and also to generate the Admin interface.



</p><p>Note that we&#8217;re using Django&#8217;s various model fields. Most of it should be self-explanatory, but if you want to learn more about each type, check out the <a href="http://www.djangoproject.com/documentation/model-api/" class="external text" title="http://www.djangoproject.com/documentation/model-api/" rel="nofollow">Django documentation</a>. Also be aware that there are quite a few more field types available. This is only one example.

</p><p>One thing worth mentioning is the <code>body_html = models.TextField(blank=True)</code> line. What&#8217;s up with that <code>blank=True</code> bit? Well that information is part of Django&#8217;s built-in Admin error checking.

</p><p>Unless you tell it otherwise, all fields in your model will create NOT NULL columns in your database. To allow for null columns, we would just add <code>null=True</code>. But adding <code>null=True</code> only affects the database, Django&#8217;s Admin system would still complain that it needs the information. To get around that, we simply add the <code>blank=True</code>.



</p><p>In this case, what we&#8217;re going to do is fill in the <code>body_html</code> field programatically &#8212; after we hit save in the Admin and before Django actually writes to the database. So, we need the Admin section to allow <code>body_html</code> to be blank, but not null.

</p><p>Also worth mentioning is the <code>Meta</code> class. <code>Meta</code> handles things like how Django should order our entries and what the name of the class would be. By default, Django would refer to our class as &#8220;Entrys.&#8221; That offends my grammatical senses, so we&#8217;ll just explicitly tell Django the proper plural name of &#8220;entries.&#8221;

</p><p>Next, we have a few function definitions. All Python objects should return their name. Django recently added unicode support, so we&#8217;ll return our name in unicode. Then there&#8217;s <code>get_absolute_url</code>. As you might imagine this refers to the entry&#8217;s permalink page.



</p><p>When we get to creating templates, we&#8217;ll use this to put in our permalinks. That way if you ever decide to change your permalinks you only have to change one line and your entire site will update accordingly &#8212; very slick.

</p><p>The last function simply overrides Django&#8217;s save function. Every Django model has a save function, and since we didn&#8217;t expose the <code>body_html</code> field, we need to fill it in. So we grab the text from our <code>body_markdown</code> field (which is exposed in the admin), run it through the markdown filter and store it in <code>body_html</code>.

</p><p>By doing it this way, we can just call this field in our templates and we&#8217;ll get nicely formatted HTML as output, yet the process stays transparent &#8212; write in markdown, display HTML.

</p><p>If you&#8217;re not using Markdown, just delete the <code>save</code> function, there&#8217;s no need to override it if you aren&#8217;t using the Markdown module.

</p><p><br />

</p>



<a name="Check_your_head"></a><h2> <span class="mw-headline">Check your head</span></h2>

<p>Now we need to tell Django about our new apps. Open up <code>settings.py</code> again and add these lines to your list of installed apps:

</p>

<pre class="brush: js">INSTALLED_APPS = (

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.sites',

    'django.contrib.admin',

    'djangoblog.tagging',

    'djangoblog.blog',

)

</pre>

<p><br />

Once that&#8217;s done, head over to the terminal and run <code>manage.py syncdb</code>. Refresh your admin section and you should see the tagging application we downloaded. Super cool.

</p><p>But where&#8217;s our blog model? Well, even though Django knows about our blog app, we haven&#8217;t told the app what to do in the Admin section.

</p><p>So head back over to your text editor and create a new file. Name it admin.py and save it inside the &#8220;blog&#8221; folder. Now add these lines:

</p>



<pre class="brush: js">

from django.contrib import admin



from djangoblog.blog.models import Entry



class EntryAdmin(admin.ModelAdmin):

    list_display = ('title', 'pub_date','enable_comments', 'status')

    search_fields = ['title', 'body_markdown']

    list_filter = ('pub_date', 'enable_comments', 'status')

    prepopulated_fields = {"slug"&nbsp;: ('title',)}

    fieldsets = (

		(None, {'fields': (('title', 'status'), 'body_markdown', ('pub_date', 'enable_comments'), 'tags', 'slug')}),

    )



admin.site.register(Entry, EntryAdmin)

</pre>

<p>OK, what does all that do?

</p><p>The first thing we do is import Django&#8217;s admin class, as you might suspect, admin controls how the admin interface looks. Now, these customizations are entirely optional. You could simply write <code>pass</code> and go with the default admin layout. However I&#8217;ve customized a few things and added some filters to the admin list view so we can sort and filter our entries. Note that if you aren&#8217;t using Markdown, just replace <code>body_markdown</code> with <code>body_html</code>.

</p><p>We&#8217;ve also used a handy tool, Django&#8217;s prepopulated_fields, which will use a bit of Javascript to automatically build a slug from our title.

</p><p>The last step is to register our admin customizations with Django&#8217;s admin app. If you aren&#8217;t actually making any customizations, you could just write the model name. In other words the admin class name is optional.

</p><p>If you refresh your admin page you should now see the blog model with a link to create and edit blog entries.



</p><p>Want more control over what shows up in your admin? For instance, if it&#8217;s a personal site, you probably don&#8217;t need the &#8220;Users&#8221; section in the admin. Let&#8217;s customize what shows up. To do that we&#8217;re going to create a new file, again named admin.py, but put this one at the project level, inside the djangoblog folder.

</p><p>Okay now paste in this code:

</p>

<pre class="brush: js">from django.contrib import admin

from djangoblog.blog.models import Entry

from djangoblog.blog.admin import EntryAdmin



class AdminSite(admin.AdminSite):

    pass







site = AdminSite()

site.register(Entry, EntryAdmin)

</pre>

<p>All this does is override Django&#8217;s default AdminSite and then simply registers our Entry model and admin classes. Of course you could do more than simply pass, check the Django docs for customization tips.

</p><p>Now if you go back and refresh the admin page you should see just the things we&#8217;ve built &#8212; the Entries and Tags models.

</p>

<a name="Tweak_the_links_and_tags"></a><h2> <span class="mw-headline">Tweak the links and tags</span></h2>

<p>One last thing, let&#8217;s jump back over to our <code>models.py</code> file; we&#8217;re going to add one extra function to our blog to improve its usability. Add these lines to the bottom of your <code>models.py</code> file:



</p>

<pre class="brush: js">    def get_previous_published(self):

        return self.get_previous_by_pub_date(status__exact=1)



    def get_next_published(self):

        return self.get_next_by_pub_date(status__exact=1)



    def get_tags(self):

        return Tag.objects.get_for_object(self)



</pre>

<p>So what&#8217;s going on here?

</p><p>Django includes a bunch of built-in methods for common tasks, like displaying next and previous links on pages. The function is called <code>get_previous_by_</code> with the last bit of the function being the name of your datetime field, in our case <code>pub_date</code>. However, we included the ability to save drafts in our model, and, unfortunately, Django&#8217;s built-in function doesn&#8217;t know about our drafts. So, it will automatically include them in our next/previous links. This obviously isn&#8217;t what we want.

</p><p>So what we&#8217;ve done is wrap the Django function with a one-liner:

</p>

<pre class="brush: js">    def get_previous_published(self):

        return self.get_previous_by_pub_date(status__exact=1)

</pre>

<p>All this does is wrap the Django function with a new name <code>get_next_published</code>, call the original <code>get_previous_by_</code> function, but add a filter so that only <i>published</i> entries are included in the results.



</p><p>The last function in that set, <code>get_tags</code>, is just a time saver. There&#8217;s a good chance you&#8217;ll want to list all the tags you&#8217;ve added to your entry, so I&#8217;ve included a convenience method that does just that.

</p>

<a name="Onward_and_upward"></a><h2> <span class="mw-headline">Onward and upward</span></h2>

<p>Whew! That&#8217;s a lot of code to sort through, and we&#8217;ve glossed over a few things. But when you look at the <code>models.py</code> file and consider that from these 49 lines of code, Django was able to generate an entire blog website, it doesn&#8217;t seem like so much code at all, does it?

</p><p>Save the file and head back over to your browser. Refresh the admin page and click &#8220;Add new.&#8221; Feel free to create a few entries &#8212; blog monkey blog!

</p><p>So now we&#8217;ve got our back-end blogging system set up and everything in in place to create a public site. Feel free to take a well deserved break.

</p><p>The next thing to do is dress up the public-facing side of our blog, which is functional, yet totally vanilla. We tackle that in <a href="/2010/02/Use_URL_Patterns_and_Views_in_Django" title="Tutorial:Use URL Patterns and Views in Django"> Lesson 3: Use URL Patterns and Views in Django</a>, so click ahead once you feel ready.



</p><p>In the meantime, you&#8217;ve learned enough about Django to continue building the backend, and you can always consult the <a href="http://www.djangobook.com/en/1.0/" class="external text" title="http://www.djangobook.com/en/1.0/" rel="nofollow">Django Book</a> if you want to strike out on your own.

</p><p>Good luck!

</p>

<div id="series">

<div class="series_hdr">From the Django Tutorial series</div>

<table style="background: rgb(229, 249, 255) none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" width="620">

<tbody><tr>

<td>

<p><a href="/2010/02/Get_Started_With_Django" title="Tutorial:Get Started With Django"> Lesson 1: Get Started With Django</a><br />

<strong class="selflink"> Lesson 2: Install Django and Build Your First App</strong><br />

<a href="/2010/02/Use_URL_Patterns_and_Views_in_Django" title="Tutorial:Use URL Patterns and Views in Django"> Lesson 3: Use URL Patterns and Views in Django</a><br />

<a href="/2010/02/Use_Templates_in_Django" title="Tutorial:Use Templates in Django"> Lesson 4: User Templates in Django</a><br />

<a href="/2010/02/Integrate_Web_APIs_into_Your_Django_Site" title="Tutorial:Integrate Web APIs into Your Django Site"> Lesson 5: Use Web API Data in Django</a><br />

<a href="/2010/02/Build_a_Microblog_with_Django" title="Tutorial:Build a Microblog with Django"> Lesson 6: Build a Microblog with Django</a>

</p>

</td></tr></tbody></table>

</div><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/install_django_and_build_your_first_app/feed/</wfw:commentRss>
        <slash:comments>5</slash:comments>

        
    </item>
    
    <item>
        <title>Use URL Patterns and Views in Django</title>
        <link>http://www.webmonkey.com/2010/02/use_url_patterns_and_views_in_django/</link>
        <comments>http://www.webmonkey.com/2010/02/use_url_patterns_and_views_in_django/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=925</guid>
        		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[Last time around, we installed Django and started building a blog application. We got Django&#8217;s built-in admin system up and running and explored some third-party libraries like the django-tagging project. So far we have some cool administrative tools, but no website for the rest of the world to see. This time around, we&#8217;ll work on [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>Last time around, we <a href="/2010/02/Install_Django_and_Build_Your_First_App" title="Tutorial:Install Django and Build Your First App"> installed Django</a> and started building a blog application. We got Django&#8217;s built-in admin system up and running and explored some third-party libraries like the <a href="http://code.google.com/p/django-tagging/" class="external text" title="http://code.google.com/p/django-tagging/" rel="nofollow">django-tagging</a> project.

</p><p>So far we have some cool administrative tools, but no website for the rest of the world to see. This time around, we&#8217;ll work on displaying our content to the world by building the URL patterns and constructing some &#8220;views&#8221; &#8212; a term with a very specific meaning within the Django framework.

</p><p>Everything we&#8217;re going to do will make more sense if you understand how Django processes your visitor&#8217;s request. We went over some of this in our introduction, but here&#8217;s a quick refresher course.

</p><span id="more-925"></span>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>



<ol>

<li><a href="#How_content_is_presented">How content is presented</a></li>

<li><a href="#Working_with_urls.py">Working with urls.py</a></li>

<li><a href="#Thoughts_on_URLs">Thoughts on URLs</a></li>

<li><a href="#Being_Generic_is_Good">Being Generic is Good</a></li>



<li><a href="#Go_your_own_way">Go your own way</a></li>

<li><a href="#Conclusion">Conclusion</a></li>

</ol>

</td></tr></tbody></table>



<a name="How_content_is_presented"></a><h2> <span class="mw-headline">How content is presented</span></h2>

<p>The Django flow goes something like this:

</p><p>1) Visitor&#8217;s browser asks for a URL.<br />



2) Django matches the request against its urls.py files.<br />

3) If a match is found, Django moves on to the view that&#8217;s associated with the URL. Views are generally found inside each app in the views.py file.<br />

4) The view generally handles all the database manipulation. It grabs data and passes it on.<br />

5) A template (specified in the view) then displays that data.<br />

</p><p>Designer and coder Jeff Croft has put together a visual representation of this flow that makes it even easier to understand:

</p>

<div class="center"><div class="floatnone"><span><a href="/special/image/Django_flowchart.png" class="image" title="Django flowchart.png"><img alt="" src="/mediawiki/images/Django_flowchart.png" border="0" height="361" width="277"></a></span></div></div>

<p>See the full size original (along with explanatory text) at <a href="http://www.flickr.com/photos/jcroft/432038560/sizes/o/" class="external text" title="http://www.flickr.com/photos/jcroft/432038560/sizes/o/" rel="nofollow">Flickr</a>.

</p><p>With that in mind, let&#8217;s start building our public site by creating some URL patterns.

</p>

<a name="Working_with_urls.py"></a><h2> <span class="mw-headline">Working with urls.py</span></h2>



<p>Remember the <code>urls.py</code> file where we set up our admin URLs in the <a href="/2010/02/Install_Django_and_Build_Your_First_App" title="Tutorial:Install Django and Build Your First App"> last lesson</a>? Open that file in your favorite text editor.

</p><p>Now, we could define all our URLs in this file. But then what happens if we want to reuse this blog in an entirely separate project? We&#8217;d get a mess.

</p><p>A far better approach is to define all your app-specific URLs in a file that lives inside the app itself. In this case, we&#8217;re going to use a file inside the blog app, which will also be named <code>urls.py</code>.

</p><p>However, before we start with that file, we need to tell Django about it. So add this line to the project-wide <code>urls.py</code> file, just below the line that defines the admin URLs, like so:

</p>

<pre class="brush: js">from django.conf.urls.defaults import *

from django.contrib import admin



urlpatterns = patterns('',

    (r'^admin/(.*)', admin.site.root),

	(r'^blog/', include('djangoblog.blog.urls')),

)



</pre>

<p>OK, now head into the blog app folder and create a new <code>urls.py</code> file, which we&#8217;ll use to hold all the URLs related to our blog application.

</p>

<a name="Thoughts_on_URLs"></a><h2> <span class="mw-headline">Thoughts on URLs</span></h2>

<p>One of the nice things about Django is that it forces you to think about your URL designs, something many people don&#8217;t spend much time considering. If, perchance, you&#8217;ve never spent too much time thinking about URLs, now is good time to <a href="http://www.w3.org/Provider/Style/URI" class="external text" title="http://www.w3.org/Provider/Style/URI" rel="nofollow">read the W3C guide on the subject</a>.

</p><p>As the W3C points out, good URLs never change. In fact, even bad URLs never change &#8212; people change them. But when you change your URLs, you break everyone&#8217;s bookmarks and inbound links. So, spend a bit of time designing a good URL scheme from the beginning and you shouldn&#8217;t need to change things down the road.

</p><p>I would actually add one item to the W3Cs guidelines: good URLs are hackable. What do I mean by hackable? Let&#8217;s say our blog has URLs like:

</p>

<pre class="brush: js">http://mysite.com/blog/2008/jul/08/post-slug/

</pre>



<p>That URL would display the blog post with the slug named &#8220;post-slug&#8221; which was published on July 8, 2008.

</p><p><b>Note:</b> &#8220;Slug&#8221; is an old newspaper term. An article about fires in Nevada would probably be slugged &#8220;nv-fires&#8221; for easy identification. In this context, the slug refers to the last bit of the URL and can contain letters and dashes rather than spaces.

</p><p>Ideally, if the user heads up to their browser&#8217;s location bar and chops off the <code>post-slug/</code> bit, they would see all the blog entries from July 8, 2008. If they were to chop off <code>08/</code>, they would see all the posts from July 2008, and so on.

</p><p>In other words, the URL is hackable. Now, most people probably won&#8217;t do that. But in addition to making your site easier to navigate for the hands-on types, this rule also enforces an easy-to-use structure around which to build your site. In this case, the date-based structure was probably already obvious. But what about tags?

</p>

<pre class="brush: js">http://mysite.com/blog/tags/tag-slug/

</pre>

<p>This URL structure uses the same idea, but one-ups it. Not only can you hack the URL to get to a list of all tags (provided you create such a page), it should be obvious that you could plug just about any word into the &#8220;tag-slug&#8221; part of the URL and it effectively functions like a tag-based search engine.

</p><p>So, how do we actually build the URLs?

</p>



<a name="Being_Generic_is_Good"></a><h2> <span class="mw-headline">Being Generic is Good</span></h2>

<p>Let&#8217;s get started. Paste this code into your <code>blog/urls.py</code> file:

</p>

<pre class="brush: js">from django.conf.urls.defaults import *

from djangoblog.blog.models import Entry

from tagging.views import tagged_object_list



info_dict = {

	'queryset': Entry.objects.filter(status=1),

	'date_field': 'pub_date',

}



urlpatterns = patterns('django.views.generic.date_based',

	(r'(?P&lt;year&gt;d{4})/(?P&lt;month&gt;[a-z]{3})/(?P&lt;day&gt;w{1,2})/(?P&lt;slug&gt;[-w]+)/$', 'object_detail', dict(info_dict, slug_field='slug',template_name='blog/detail.html')),

	(r'^(?P&lt;year&gt;d{4})/(?P&lt;month&gt;[a-z]{3})/(?P&lt;day&gt;w{1,2})/(?P&lt;slug&gt;[-w]+)/$', 'object_detail', dict(info_dict, template_name='blog/list.html')),

	(r'^(?P&lt;year&gt;d{4})/(?P&lt;month&gt;[a-z]{3})/(?P&lt;day&gt;w{1,2})/$','archive_day',dict(info_dict,template_name='blog/list.html')),

	(r'^(?P&lt;year&gt;d{4})/(?P&lt;month&gt;[a-z]{3})/$','archive_month', dict(info_dict, template_name='blog/list.html')),

	(r'^(?P&lt;year&gt;d{4})/$','archive_year', dict(info_dict, template_name='blog/list.html')),

	(r'^$','archive_index', dict(info_dict, template_name='blog/list.html')),

)





</pre>

<p>Now, remember when I said that the URL patterns determine which view Django will use to grab data from our database? In that scheme, we would write our regular expressions and then point each pattern to a function in <code>views.py</code>.

</p><p>But we&#8217;re cheating a little bit here by taking advantage of some built in views that Django provides. These are known as &#8220;generic views.&#8221;

</p><p>Django&#8217;s developers wisely figured that date-based archives were likely to be a common problem that just about every site has at least some use for, so they baked in some generic data-based views.

</p><p>What we&#8217;ve done here is take advantage of the built in views to construct our URLs.

</p><p>Let&#8217;s start with <code>info_dict</code>, which is just a Python dictionary that holds two things: a queryset containing all of our public blog entries and the name of our date field in the database.

</p><p>It&#8217;s important to realize that Django querysets are lazy &#8212; Django only hits the database when the queryset is evaluated, so there&#8217;s no performance penalty for defining a queryset that looks for everything, then filtering it on a case-by-case basis. This happens to be essentially what we&#8217;ve just done.

</p><p>Passing the queryset to the generic view enables Django to automatically do whatever date sorting we need, for instance, to show all the entries from a single month or year. For more info on querysets, check out the <a href="http://www.djangoproject.com/documentation/db-api/" class="external text" title="http://www.djangoproject.com/documentation/db-api/" rel="nofollow">database API docs</a> on the Django site.

</p><p>That&#8217;s all the URL patterns list is: a regular expression that looks at the URL and figures out what view to use. The view then determines which entry or list of entries to show.

</p><p>Let&#8217;s break it down and go through each part of the URL pattern. We&#8217;ll use the first line as an example:



</p>

<pre class="brush: js">(r'(?P&lt;year&gt;d{4})/(?P&lt;month&gt;[a-z]{3})/(?P&lt;day&gt;w{1,2})/(?P&lt;slug&gt;[-w]+)/$', 'object_detail', dict(info_dict, slug_field='slug',template_name='blog/detail.html')),

</pre>

<p>The first bit:

</p>

<pre class="brush: js">(?P&lt;year&gt;d{4})/(?P&lt;month&gt;[a-z]{3})/(?P&lt;day&gt;w{1,2})/(?P&lt;slug&gt;[-w]+)/$



</pre>

<p>is the regular expression. In this case, the expression will match our permalink URLs and capture the year, month, day and slug of a particular entry. That information will then be passed to the next bit, <code>object_detail</code>, which is the name of the generic view that will pull out a single entry.

</p><p>The full path to object_detail is actually <code>django.views.generic.date_based.object_detail</code>, but since we started our urlpattern definition by including the <code>django.views.generic.date_based</code> bit, there&#8217;s no need to retype it every time, we just need to call the individual function, in this case object_detail.

</p><p>After we grab the URL info and pass it to the <code>object_detail</code> function, we also pass along a dictionary of data. Most of the time you can just pass <code>info_dict</code> here. The <code>object_detail</code> generic view is something of an exception because it needs to pass along the slug_field variable as well.



</p><p>I wanted to show some of the other data you can include as well, so I wrapped it in the <code>dict</code> your see above. In this case, we&#8217;ve passed <code>info_dict</code>, the slug_field and the name of the template Django should use to display the data.

</p><p>The rest of the patterns just work their way back up the URL using ever-shortening regular expressions until we get to nothing, which would be the URL: http:/mysite.com/blog/.

</p><p>We&#8217;ll be using that URL as the location of our archive page. So, I guess you can think of this as a tumblelog rather than a traditional blog, which would probably have separate archive and home pages. Naturally, you can tweak the URL patterns to fit whatever design you&#8217;d like.

</p><p>Django&#8217;s generic views are incredibly powerful, and there are quite a few other options beyond just the date-based ones we&#8217;ve used here. There&#8217;s also a super-handy built-in pagination system for some generic views. Be sure to read through the <a href="http://www.djangoproject.com/documentation/generic_views/" class="external text" title="http://www.djangoproject.com/documentation/generic_views/" rel="nofollow">documentation on the Django website</a> and also have a look at <a href="http://www.b-list.org/weblog/2006/nov/16/django-tips-get-most-out-generic-views/" class="external text" title="http://www.b-list.org/weblog/2006/nov/16/django-tips-get-most-out-generic-views/" rel="nofollow">James Bennett&#8217;s excellent guide</a> to the various ways you can wrap and extend generic views.

</p>

<a name="Go_your_own_way"></a><h2> <span class="mw-headline">Go your own way </span></h2>



<p>Django&#8217;s generic views can save you quite a bit of time, but you will probably encounter some situations where they don&#8217;t quite do exactly what you want. When that happens, it&#8217;s time to write your own views.

</p><p>Fear not, writing a custom view isn&#8217;t hard.

</p><p>We&#8217;ve pretty much covered our blogs URLs, from date-based archives to the detail pages, but what about the pages that display our entries by tag?

</p><p>The tagging application actually includes some views that we could use. But for the sake of example, we&#8217;ll write some custom views. Rather than overwriting what&#8217;s already in the tagging application, we&#8217;re just going to create a views file that lives on its own in our main project folder.

</p><p>So, inside the &#8220;djangoblog&#8221; folder create a new file named <code>tag_views.py</code>. Remember, before we get started there, we need to tell Django about the <code>tag_views</code> file, so open up <code>djangoblog/urls.py</code> and add the last line below what&#8217;s already there:

</p>

<pre class="brush: js">urlpatterns = patterns('',

	(r'^admin/(.*)', admin.site.root),

	(r'^blog/', include('djangoblog.blog.urls')),

	(r'^tags/(?P&lt;slug&gt;[a-zA-Z0-9_.-]+)/$', 'djangoblog.tag_views.tag_detail'),

)



</pre>

<p>Here, we haven&#8217;t included another <code>url.py</code> file like we did with the lines above. You could argue that we should, but just to show that you don&#8217;t <i>have</i> to, we&#8217;ll just point directly to our <code>tag_views.py</code> file which will soon have a function named <code>tag_detail</code>. Note that in the tag URL, we&#8217;re capturing the slug paramater. We&#8217;ll use that in just a minute to filter our blog entries by tag.

</p><p>Now it&#8217;s time to create the tag_detail function in the <code>tag_views.py</code> file. Open up that file in your text editor and paste in this code:



</p><p><br />

</p>

<pre class="brush: js">from django.views.generic.list_detail import object_detail



from tagging.models import Tag,TaggedItem

from blog.models import Entry



def tag_detail(request, slug):

	unslug = slug.replace('-', ' ')

	tag = Tag.objects.get(name=unslug)

	qs = TaggedItem.objects.get_by_model(Entry, tag)

	return object_list(request, queryset=qs, extra_context={'tag':slug}, template_name='tags/detail.html')

</pre>

<p>What&#8217;s going on here? Well, ignore the first line for now, we&#8217;ll get to that in a minute. We import all the things we need &#8212; in this case, the Tag and TaggedItem classes from django tagging and then our own Entry class. Then we define the <code>tag_detail</code> function, which is just an ordinary Python function that takes two parameters. The first is <code>request</code> which Django passes to all view functions, and the second is the slug paramater we defined in our URL pattern above.

</p><p>Now because we&#8217;re using a slug for our tag URLs, but strings of words with spaces for our tags, we need to get rid of the dashes and replace them with spaces (Remember, a slug can contain letters and dashes, but not spaces).

</p><p>Because our slug parameter is just a string, we can use the normal Python string function to make that replacement.

</p><p>In the next line, we look up our tag name in the database using the <code>objects</code> manager. Then we take advantage of django-tagging&#8217;s built in function <code>get_by_model</code> to grab all the entries with the given tag.



</p><p>The last step is to return something so that Django can load our template and display the entries to our visitor. To do that we&#8217;re going to use another of Django&#8217;s generic view functions &#8212; <code>object_detail</code> from the generic list views.

</p><p><code>Object_detail</code> requires a few things. First is the request object, then the queryset of results. After that, I&#8217;ve added an extra context variable named tag, so our template will be aware not just what entries to display, but also the current tag. Finally, the last item simply tells Django which template to use.

</p><p>We haven&#8217;t yet created a URL for <code><a href="http://mysite.com/blog/tags/" class="external free" title="http://mysite.com/blog/tags/" rel="nofollow">http://mysite.com/blog/tags/</a></code> to list all our tags, but that&#8217;s a good stepping stone to practice writing a view function on your own. Here&#8217;s a hint: you can use pretty much the same code we used for the <code>tag_detail</code> function, but you don&#8217;t need to worry about the <code>slug</code> param. And instead of looking up TaggedItems, just grab all the tags (i.e. <code>qs = Tag.objects.all()</code>)



</p>

<a name="Conclusion"></a><h2> <span class="mw-headline"> Conclusion </span></h2>

<p>And there you have it, a quick and dirty overview of how URL patterns and view work in Django.

</p><p>If you point your browser to our development URL (<a href="http://127.0.0.1:8000/blog/" class="external free" title="http://127.0.0.1:8000/blog/" rel="nofollow">http://127.0.0.1:8000/blog/</a>) you should see a Django error page complaining that the template blog/list.html does not exist. This is true, since we haven&#8217;t created it yet (visiting the tag pages will give you &#8220;list index out of range&#8221; error, also due to the missing templates).

</p><p>But don&#8217;t worry &#8212; in the next lesson, we&#8217;ll dive into Django&#8217;s template system and explore all the cool things we can do, including how to write custom template filters and more.

</p><p>See you then!

</p><p><br />

</p>

<div id="series">

<div class="series_hdr">From the Django Tutorial series</div>

<table style="background: rgb(229, 249, 255) none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" width="620">



<tbody><tr>

<td>

<p><a href="/2010/02/Get_Started_With_Django" title="Tutorial:Get Started With Django"> Lesson 1: Get Started With Django</a><br />

<a href="/2010/02/Install_Django_and_Build_Your_First_App" title="Tutorial:Install Django and Build Your First App"> Lesson 2: Install Django and Build Your First App</a><br />

<strong class="selflink"> Lesson 3: Use URL Patterns and Views in Django</strong><br />

<a href="/2010/02/Use_Templates_in_Django" title="Tutorial:Use Templates in Django"> Lesson 4: User Templates in Django</a><br />

<a href="/2010/02/Integrate_Web_APIs_into_Your_Django_Site" title="Tutorial:Integrate Web APIs into Your Django Site"> Lesson 5: Use Web API Data in Django</a><br />



<a href="/2010/02/Build_a_Microblog_with_Django" title="Tutorial:Build a Microblog with Django"> Lesson 6: Build a Microblog with Django</a>

</p>

</td></tr></tbody></table>

</div><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/use_url_patterns_and_views_in_django/feed/</wfw:commentRss>
        <slash:comments>2</slash:comments>

        
    </item>
    
    <item>
        <title>Use Templates in Django</title>
        <link>http://www.webmonkey.com/2010/02/use_templates_in_django/</link>
        <comments>http://www.webmonkey.com/2010/02/use_templates_in_django/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=927</guid>
        		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[This is part 4 of Webmonkey&#8217;s introductory Django tutorial. If you&#8217;re arriving here to learn about getting started with Django, start back at the beginning with Lesson 1. When we left off last time, we had defined some URLs for our blog and constructed a custom view to handle displaying posts by tag. If you [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>This is part 4 of Webmonkey&#8217;s introductory Django tutorial. If you&#8217;re arriving here to learn about getting started with Django, start back at the beginning with <a href="/2010/02/Get_Started_With_Django" title="Tutorial:Get Started With Django"> Lesson 1</a>.

</p><p>When we left off last time, we had defined some URLs for our blog and constructed a custom view to handle displaying posts by tag. If you point your browser to our development URL at this point, (<a href="http://127.0.0.1:8000/blog/" class="external free" title="http://127.0.0.1:8000/blog/" rel="nofollow">http://127.0.0.1:8000/blog/</a>) you&#8217;ll still see a Django error page complaining that the template blog/list.html does not exist. Don&#8217;t panic, it&#8217;s true &#8212; we haven&#8217;t created it yet.

</p><p>It&#8217;s time to tackle the last aspect of Django, the template syntax.

</p><p><br />

</p><span id="more-927"></span>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>



<ol>

<li><a href="#Create_some_templates">Create some templates</a></li>

<li><a href="#Inheritance">Inheritance</a></li>

<li><a href="#A_simple_template">A simple template</a>

<ol>

<li><a href="#Using_built-in_filters">Using built-in filters</a></li>



<li><a href="#Displaying_tags">Displaying tags</a></li>

</ol>

</li>

<li><a href="#Finishing_up_the_template">Finishing up the template</a></li>

<li><a href="#More_about_built-in_template_filters">More about built-in template filters</a></li>

<li><a href="#Roll_your_own_template_tags">Roll your own template tags</a></li>



<li><a href="#Links_and_other_resources">Links and other resources</a></li>

</ol>

</td></tr></tbody></table>



<a name="Create_some_templates"></a><h2> <span class="mw-headline">Create some templates</span></h2>

<p>If you look back through the code we&#8217;ve written so far, you&#8217;ll find that we&#8217;ve point Django to a number of templates (check out the [Tutorial:Use URL Patterns and Views in Django | urlpatterns code] and the custom view we wrote).

</p><p>The templates we&#8217;ve defined need to be created. We&#8217;re going to use the following names within this directory structure:

</p>

<pre class="brush: js">djangoblog

	- templates

		-blog

			list.html

			detail.html

		-tags

			list.html

</pre>

<p>You can go ahead and create that directory structure &#8212; just create a folder in your main &#8220;djangoblog&#8221; folder and name it &#8220;templates.&#8221; Inside that, create two folders named &#8220;blog&#8221; and &#8220;tags.&#8221;

</p><p>Then create your <code>list.html</code> and <code>detail.html</code> files.



</p><p>Note: The .html extension is totally optional &#8212; I prefer it because it turns on the syntax highlighting feature in my text editor, but you can use any extension you like.

</p>

<a name="Inheritance"></a><h2> <span class="mw-headline">Inheritance</span></h2>

<p>If we step back for a minute and think about our blog and what our templates need to display, the first thing that jumps out at you is that there&#8217;s a whole bunch of stuff that&#8217;s common to every page &#8212; a header, site navigation, sidebar, footer, and so on.

</p><p>It would be silly (and a egregious violation of the DRY principle) if we wrote that code more than once. Luckily, like most good template languages, Django provides a way to extend a single template file. We can define our site-wide components once and then simply inherit from that file, adding in the aspects of the site that do change.

</p><p>So before we dive into the detail pages, let&#8217;s first create a base file. Being the creative type, I generally call the file <code>base.html</code>. So inside the templates folder you created above, add a new file called <code>base.html</code>.

</p>

<a name="A_simple_template"></a><h2> <span class="mw-headline">A simple template</span></h2>

<p>Open that file in your text editor. Let&#8217;s sketch out some of the site-wide HTML we might need. For the sake of this tutorial, I&#8217;ve kept things pretty simple, but feel free to get as fancy as you want with your HTML. Here&#8217;s a basic starting point:



</p>

<pre class="brush: js">&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;

&lt;html lang="en"&gt;

	&lt;head&gt;

		&lt;title&gt;My Site - {%block pagetitle&nbsp;%}{% endblock&nbsp;%}&lt;/title&gt;

	&lt;/head&gt;



	&lt;body&gt;

		&lt;div id="header"&gt;My Site&lt;/div&gt;

		&lt;div id="nav"&gt;

			&lt;ul&gt;

				&lt;li&gt;&lt;a href="/"&gt;home&lt;/a&gt;&lt;/li&gt;



				&lt;li&gt;&lt;a href="/blog/"&gt;Blog&lt;/a&gt;&lt;/li&gt;

				&lt;li&gt;&lt;a href="/links/"&gt;Links&lt;/a&gt;&lt;/li&gt;

				&lt;li&gt;&lt;a href="/about/"&gt;About&lt;/a&gt;&lt;/li&gt;



			&lt;/ul&gt;

		&lt;/div&gt;

		&lt;div id="content"&gt;

			&lt;div id="primary"&gt;

				&lt;h1&gt;{% block title&nbsp;%}{% endblock&nbsp;%}&lt;/h1&gt;



				{% block primary&nbsp;%}{% endblock&nbsp;%}

			&lt;/div&gt;

			&lt;div id="secondary"&gt;

				&lt;h3&gt;Recent Entries:&lt;/h3&gt;

			&lt;div&gt;



		&lt;/div&gt;

	&lt;/body&gt;

&lt;/html&gt;

</pre>

<p>That should be pretty self explanatory, save perhaps the curious things enclosed in curly brackets, the <code>{%&nbsp;%}</code> bits. What up with that stuff?

</p><p>That is Django&#8217;s template syntax for creating blocks which other templates can plug data into. In this case we&#8217;re creating a base template with a few blocks (think of them as holes) and our other templates will extend this and fill in the holes.

</p><p>To see what I mean let&#8217;s create the blog/list.html template. Add a new blog folder in the templates folder (if you haven&#8217;t already) and create a file list.html. Now open that up and past in the line:

</p>



<pre class="brush: js">{% extends 'base.html'&nbsp;%}</pre>.

<p>Now, if you revisit <a href="http://127.0.0.1:8000/blog/" class="external free" title="http://127.0.0.1:8000/blog/" rel="nofollow">http://127.0.0.1:8000/blog/</a> the template not found error should be gone. In its place, you should see everything we just put in <code>base.html</code>.

</p><p>Not much, I&#8217;m afraid. But fear not &#8212; now that we&#8217;re extending <code>base.html</code>, we can start plugging in some values for those blocks we created earlier.

</p><p>Add this below the extends statement:

</p>

<pre class="brush: js">{% block pagetitle&nbsp;%}Tumblelog{% endblock&nbsp;%}

{% block title&nbsp;%}My Page Headline{% endblock&nbsp;%}

{% block primary&nbsp;%}

{% for object in latest&nbsp;%}

	&lt;h2&gt;{{ object.title }}&lt;/h2&gt;



	&lt;p&gt;{{ object.pub_date }}&lt;/p&gt;

	 {{ object.body_html|truncatewords_html:"20"|safe }}

	&lt;p&gt;tags: {% for tag in object.get_tags%}&lt;a href="/blog/tags/{{tag.name|slugify}}/"&gt;{{tag}}&lt;/a&gt;{% endfor&nbsp;%}&lt;/p&gt;

	&lt;p&gt;&lt;a href="{{object.get_absolute_url}}"&gt;read more&lt;/a&gt;&lt;/p&gt;



{% endfor&nbsp;%}

{% endblock&nbsp;%}

</pre>

<p>The first thing we do is fill in our page title block in the head tags. Then we do the same for the displayed title. The next block we fill in is the primary content block. Here&#8217;s where we display the data that our generic view grabbed for us.

</p><p>The Django template syntax can be considered fairly &#8220;Pythonic,&#8221; in that your define loops using the same <code>for x in dataset</code> syntax as Python. In this case, the generic view function <code>object_detail</code> passes in a variable named latest. By default, this displays the fifteen latest entries, though you can go back to the <code>urls.py</code> file and increase that number using the <code>num_latest</code> param.



</p><p>All we do is construct a loop using the <code>latest</code> variable. Then within that loop we pull out some of our data &#8212; again, accessing an objects attributes uses the Python-like dot accessor methods.

</p>

<a name="Using_built-in_filters"></a><h3> <span class="mw-headline">Using built-in filters</span></h3>

<p>The only part that requires additional explaining is the <code>object.body_html</code> section where we&#8217;ve applied two built-in Django template filters, <code>truncatewords_html</code> and <code>safe</code>.



</p><p><code>Truncatewords_html</code> should be fairly obvious &#8212; this clips the body of our post after twenty words, but also preserves the structure of the HTML by appending any closing tags to make sure the HTML remains intact.

</p><p>The <code>safe</code> filter simply tells Django that it&#8217;s OK to display HTML. Without the safe filter, Django will automatically escape all HTML entities and tags. Autoescaping is a nice feature for avoiding nefarious XSS attacks and the like, but in this case, since we trust the source, we&#8217;ll let the HTML through.

</p>

<a name="Displaying_tags"></a><h3> <span class="mw-headline">Displaying tags</span></h3>

<p>All fine so far, but what about tags? We have tags on our entries, so we might as well display them. This is what we do in the next line.

</p><p>You&#8217;ll notice that in that line, we have a loop within a loop. Remember when we created our models and we added a <code>get_tags</code> method to return all the tags for each entry? Well, here it is in action.

</p><p>That will loop through all the tags for each entry and display them along with a link to that tag&#8217;s permalink page. And note that we&#8217;ve used the slugify filter to make sure than any multiword tags will be hyphenated in the URL



</p><p>Note: If you remember back when we wrote our custom tag view, we used a string replace function to &#8220;unslugify&#8221; the URL for lookup in the datebase.

</p><p><br />

</p>

<a name="Finishing_up_the_template"></a><h2> <span class="mw-headline">Finishing up the template</span></h2>

<p>The last line calls the <code>get_absolute_url</code> function that we defined when we built our model in the last lesson. This provides a link to the permalink page for each entry in the list.

</p>

So click that link and what happens? Error page. You need to define the detail.html template. That&#8217;s not to hard, just create the file, add the extends base.html instruction at the top and fill in the blank blocks like title and primary. This time there&#8217;s no need to loop through anything since there&#8217;s only one object. Just call it directly like we did inside the loop on the archive page: <pre class="brush: js">{{object.title}}</pre> etc.

<p>The code might look something like this:

</p>



<pre class="brush: js">{% block pagetitle&nbsp;%}{{object.title}}{% endblock&nbsp;%}

{% block title&nbsp;%}{{object.title}}{% endblock&nbsp;%}

{% block primary&nbsp;%}

	&lt;ul class="page-nav"&gt;

		{% if object.get_previous_published%}

		&lt;li&gt;

			&lt;a href="{{ object.get_previous_published.get_absolute_url }}" title=" {{object.get_previous_published.title}}"&gt;« previous&lt;/a&gt;



		&lt;/li&gt;

		{%endif%}

		{% if object.get_next_published%}

			&lt;li&gt;

				&lt;a href="{{ object.get_next_published.get_absolute_url }}" title=" {{object.get_next_published.title}}"&gt;next »&lt;/a&gt;

			&lt;/li&gt;

		{%endif%}

    &lt;/ul&gt;



	&lt;h2&gt;{{ object.title }}&lt;/h2&gt;

	&lt;p&gt;{{ object.pub_date }}&lt;/p&gt;

	 {{ object.body_html|safe }}

	&lt;p&gt;tags: {% for tag in object.get_tags%}&lt;a href="/blog/tags/{{tag.name|slugify}}/"&gt;{{tag}}&lt;/a&gt;{% endfor&nbsp;%}&lt;/p&gt;



	&lt;p&gt;&lt;a href="{{object.get_absolute_url}}"&gt;read more&lt;/a&gt;&lt;/p&gt;

{% endblock&nbsp;%}

</pre>

<p>Note that I&#8217;ve made use of those <code>get_next_published</code> and <code>get_previous_published</code> functions that we defined way back when wrote our models. That way, users have some handy next and previous links for navigating through your permalink pages.



</p><p>Naturally you can get much more sophisticated with your HTML than this simple example.

</p><p>To create the templates for the tag pages, you&#8217;ll essentially do the same thing. In our custom tag view we returned a list of all the entries in an object named <code>object_list</code>. So in order to display them, just loop through <code>object_list</code> like we did with the <code>latest</code> variable above.

</p>

<a name="More_about_built-in_template_filters"></a><h2> <span class="mw-headline">More about built-in template filters</span></h2>

<p>Before we move on, a slight digression.

</p><p>It&#8217;s worth paying a visit to the <a href="http://www.djangoproject.com/documentation/templates/" class="external text" title="http://www.djangoproject.com/documentation/templates/" rel="nofollow">Django documentation on template filters and tags</a>. There&#8217;s a whole bunch of useful stuff built in to Django. You can use <code>{% if&nbsp;%}</code> tags to narrow and filter results, and there&#8217;s also <code>{% else&nbsp;%}</code>, <code>{% ifequal var1 var2&nbsp;%}</code>, <code>{% ifnotequal var1 var2&nbsp;%}</code> and most other common programming structures.



</p><p>Then there&#8217;s a host of template filters, like the <code>truncatewords_html</code> and <code>safe</code> filters we used above. For instance, there&#8217;s a handy <code>date</code> filter if you&#8217;d like to display your post date in something a little sexier than a UNIX timestamp.

</p><p>Here&#8217;s what that would look like using the &#8220;date&#8221; filter:

</p>

<pre class="brush: js">{{object.pub_date|date:"D d M Y"}}</pre>

<p>Another great filter is the <code>timesince</code> filter which will automatically convert a date into syntax like &#8220;1 week, 2 days ago&#8221;.



</p><p>There are also filters for escaping ampersands, escaping JavaScript, adding line breaks, removing HTML, converting to upper/lowercase and dozens more. In fact in two and a half years of building sites with Django I&#8217;ve only needed to write a custom filter once. Naturally your mileage may vary somewhat.

</p>

<a name="Roll_your_own_template_tags"></a><h2> <span class="mw-headline">Roll your own template tags</span></h2>

<p>One thing I do frequently do is write custom template &#8220;tags.&#8221; Template tags are perhaps one of the more confusing aspects of Django, since they still have a little bit of &#8220;magic&#8221; in them. But luckily they aren&#8217;t too hard to work with.

</p><p>Template tags are a way of extending the Django template system to use it in project specific ways. For instance, custom template tags are a perfect way to handle things that don&#8217;t make sense in a view, but do require some database logic.

</p><p>Perhaps the best example is something like a sidebar. So far ours is empty, but we can easily add a list of our most recent blog posts.

</p><p>We could write a filter that specifically fetches blog entries, but then what happens when we add links in the next lesson and want to display the most recent links? Write another template filter? That&#8217;s not very DRY! Instead, let&#8217;s just write a filter that fetches the most recent entries from any model with a date field.

</p><p>In fact we don&#8217;t even need to really write it. James Bennett has already <a href="http://www.b-list.org/weblog/2006/jun/07/django-tips-write-better-template-tags/" class="external text" title="http://www.b-list.org/weblog/2006/jun/07/django-tips-write-better-template-tags/" rel="nofollow">written some great reusable code</a> so we&#8217;ll just use that. I strongly recommend that you have read through James&#8217; tutorial so you can see how and why this code works.

</p><p>Open a new file and paste in this code:

</p>

<pre class="brush: js">from django.template import Library, Node

from django.db.models import get_model



register = Library()



class LatestContentNode(Node):

    def __init__(self, model, num, varname):

        self.num, self.varname = num, varname

        self.model = get_model(*model.split('.'))



    def render(self, context):

        context[self.varname] = self.model._default_manager.all()[:self.num]

        return ''



def get_latest(parser, token):

    bits = token.contents.split()

    if len(bits)&nbsp;!= 5:

        raise TemplateSyntaxError, "get_latest tag takes exactly four arguments"

    if bits[3]&nbsp;!= 'as':

        raise TemplateSyntaxError, "third argument to get_latest tag must be 'as'"

    return LatestContentNode(bits[1], bits[2], bits[4])



get_latest = register.tag(get_latest)





</pre>

<p>Now save that file as &#8220;get_latest.py&#8221; in a new folder within the blog app named &#8220;templatetags&#8221;. The folder name and location are important since Django only looks up template tags in specific locations. You also need to create an empty file named &#8220;__init__.py&#8221; inside the &#8220;templatetags&#8221; folder.

</p><p>One thing to note about this code, if you look closely you&#8217;ll notice that our template tag is going to fetch all entries, not just the public ones. In other words, our model allows for draft posts, but our template tag doesn&#8217;t.

</p><p>This is the line in question:

</p>

<pre class="brush: js">self.model._default_manager.all()

</pre>

<p>There are two ways around this, one is quick and dirty &#8212; just change that line to filter only published entries. In other words:

</p>

<pre class="brush: js">self.model._default_manager.filter(status=1)

</pre>

<p>The better (and cleaner) way to do it would be overwrite the default manager for our Entry model. However, that&#8217;s a little beyond the scope of this article, so for now we&#8217;ll just use the quick and dirty method.

</p><p>Now open up <code>base.html</code> again and add this line at the top:

</p>



<pre class="brush: js">{% load get_latest&nbsp;%}

</pre>

<p>That tells Django to load the template tag, but then we need to grab the actual data. So, head down to the sidebar section and replace it with this code:

</p>

<pre class="brush: js">&lt;div id="secondary"&gt;

	&lt;h3&gt;Recent Entries:&lt;/h3&gt;

	{% get_latest blog.Entry 5 as recent_posts&nbsp;%}

    &lt;ul class="archive"&gt;



    	{% for obj in recent_posts&nbsp;%}

		&lt;li&gt;

			&lt;a href="{{ obj.get_absolute_url }}" title="Permanent Link to {{ obj.title}}"&gt;{{ obj.title}}&lt;/a&gt;

		&lt;/li&gt;

    	{% endfor&nbsp;%}

	&lt;/ul&gt;



&lt;div&gt;

</pre>

<p>If you want to override that in templates that are inheriting from <code>base.html</code>, just wrap that code in a {% block&nbsp;%} tag and then replace it with something else in the new template.

</p>

<a name="Links_and_other_resources"></a><h2> <span class="mw-headline">Links and other resources</span></h2>

<p>The Django template system is quite vast in terms of capabilities, and we&#8217;ve really just scratched the surface here.

</p><p>Make sure you <a href="http://www.djangoproject.com/documentation/templates_python/" class="external text" title="http://www.djangoproject.com/documentation/templates_python/" rel="nofollow">read through the documentation for Python programmers</a> as well as <a href="http://www.djangoproject.com/documentation/templates/" class="external text" title="http://www.djangoproject.com/documentation/templates/" rel="nofollow">the documentation for template authors</a> and familiarize yourself with all the various built in tags and filters. Another great article is Jeff Croft&#8217;s <a href="http://jeffcroft.com/blog/2006/feb/21/django-templates-an-introduction/" class="external text" title="http://jeffcroft.com/blog/2006/feb/21/django-templates-an-introduction/" rel="nofollow">Django Templates: An Introduction</a>.



</p><p>It&#8217;s worth noting that there&#8217;s an extensive collection of useful filters and template tags on the <a href="http://www.djangosnippets.org/" class="external text" title="http://www.djangosnippets.org/" rel="nofollow">Django Snippets site</a>. If you ever find yourself needing a custom tag or filter, have a look through there and see if anyone has already written something that works for your project.

</p><p>I should also point out that if you just don&#8217;t for whatever reason like Django&#8217;s template system, it&#8217;s possible drop in another template language, like <a href="http://cheetahtemplate.sourceforge.net/" class="external text" title="http://cheetahtemplate.sourceforge.net/" rel="nofollow">Cheetah</a> or others.

</p><p>Be sure to stop by for our next installment when we&#8217;ll tackle a plan to import, store and display our del.icio.us bookmarks. See you then!

</p>

<div id="series">

<div class="series_hdr">From the Django Tutorial series</div>

<table style="background: rgb(229, 249, 255) none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" width="620">

<tbody><tr>

<td>

<p><a href="/2010/02/Get_Started_With_Django" title="Tutorial:Get Started With Django"> Lesson 1: Get Started With Django</a><br />



<a href="/2010/02/Install_Django_and_Build_Your_First_App" title="Tutorial:Install Django and Build Your First App"> Lesson 2: Install Django and Build Your First App</a><br />

<a href="/2010/02/Use_URL_Patterns_and_Views_in_Django" title="Tutorial:Use URL Patterns and Views in Django"> Lesson 3: Use URL Patterns and Views in Django</a><br />

<strong class="selflink"> Lesson 4: User Templates in Django</strong><br />

<a href="/2010/02/Integrate_Web_APIs_into_Your_Django_Site" title="Tutorial:Integrate Web APIs into Your Django Site"> Lesson 5: Use Web API Data in Django</a><br />

<a href="/2010/02/Build_a_Microblog_with_Django" title="Tutorial:Build a Microblog with Django"> Lesson 6: Build a Microblog with Django</a>

</p>

</td></tr></tbody></table>



</div><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/use_templates_in_django/feed/</wfw:commentRss>
        <slash:comments>3</slash:comments>

        
    </item>
    
    <item>
        <title>Integrate Web APIs into Your Django Site</title>
        <link>http://www.webmonkey.com/2010/02/integrate_web_apis_into_your_django_site/</link>
        <comments>http://www.webmonkey.com/2010/02/integrate_web_apis_into_your_django_site/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=929</guid>
        		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[Welcome back! If you&#8217;ve been following along our entire series of tutorials on building sites with Django, you&#8217;ll (by now) have built a blog website with date-based archives and some nice extras such as tagging and Markdown support. Along the way, we also ported our app over to the new Newforms Admin version of Django [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>Welcome back! If you&#8217;ve been following along our entire series of tutorials on building sites with Django, you&#8217;ll (by now) have built a blog website with date-based archives and some nice extras such as tagging and Markdown support.

</p><p>Along the way, we also ported our app over to the new Newforms Admin version of Django so that we&#8217;ll be all ready to go when Django hits version 1.0. If you haven&#8217;t done that yet, <a href="/2010/02/Django_Newforms_Admin_Migration" title="Tutorial:Django Newforms Admin Migration"> be sure to do it before we continue</a>.

</p><span id="more-929"></span>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>



<ol>

<li><a href="#Delicious_data">Delicious data</a></li>

<li><a href="#Building_the_model">Building the model</a></li>

<li><a href="#Building_a_Delicious_client">Building a Delicious client</a></li>

<li><a href="#Using_our_new_client">Using our new client</a></li>



<li><a href="#It.27s_all_in_the_timing">It&#8217;s all in the timing</a></li>

<li><a href="#Displaying_links">Displaying links</a></li>

<li><a href="#Conclusion">Conclusion</a></li>

</ol>

</td></tr></tbody></table>



<a name="Delicious_data"></a><h2> <span class="mw-headline">Delicious data</span></h2>



<p>Now let&#8217;s branch out a little bit. Blogs are fine and dandy, but what about some of the cool web services we all use &#8212; Flickr, Delicious, Upcoming and the like. Wouldn&#8217;t it be cool if you could pull custom data from those services and display it on our site?

</p><p>I&#8217;m going to walk you through integrating data from <a href="http://www.delicious.com" class="external text" title="http://www.delicious.com" rel="nofollow">Delicious</a>, the popular social bookmarking site, to power your own link blog. I&#8217;ve chosen Delicious because you&#8217;ll easily be able to take the basic outline we&#8217;ll use and apply it to any service with the decent API.

</p><p>The way our setup will work is whenever we want to post a link to our site, we&#8217;ll take advantage of the nice Delicious front-end tools like browser add-ons and bookmarklets. We&#8217;ll then use the Delicious API to pull that info into our own site.

</p><p>Before we get started, you might be wondering why? What&#8217;s the point when there are dead simple cut-and-paste JavaScript widgets that can already do that for us?

</p><p>Well it&#8217;s true, there are some easier ways to integrate Delicious data, but JavaScript widgets don&#8217;t allow us to store the data locally on our own server, and that&#8217;s the win. There are two reasons local data is better. First, if Delicious goes down or the server stops responding for some reason, our local app is unaffected and keeps humming along as usual. Second, if Delicious ever goes away permanently or if you simply find another service you like better, it isn&#8217;t hard to add in the new service without affecting the existing data.

</p><p>Convinced? OK let&#8217;s get started.

</p>

<a name="Building_the_model"></a><h2> <span class="mw-headline">Building the model</span></h2>

<p>The first thing we&#8217;ll do is create a new app. Why not just add a bookmark to our blog app? Well you could, but I&#8217;ve broken it out on its own for portability and for easy reusability. So, create a new folder in our djangoblog project and name it &#8220;links.&#8221;

</p><p>Now in the links folder, create a new file called &#8220;models.py&#8221; (and don&#8217;t forget to add an __init__.py file in the links folder as well, so Python can access it). Open models.py in your text editor and add these lines:

</p>

<pre class="brush: js">from django.db import models



from tagging.fields import TagField

from tagging.models import Tag



class Link(models.Model):

    title = models.CharField(max_length=200)

    description = models.TextField()

    url = models.CharField(max_length=400)

    date = models.DateTimeField('Date published')

    tags = TagField()

    status = models.IntegerField(default=1)



    class Meta:

        ordering = ('-date',)

        get_latest_by = 'date'



    def __unicode__(self):

        return u'%s'&nbsp;%(self.title)



    def get_absolute_url(self):

        return "/link/%s/"&nbsp;%(self.id)



    def get_tags(self):

        return Tag.objects.get_for_object(self)







</pre>

<p>Look familiar? It should. It&#8217;s basically a very simplified version of our blog model. Now let&#8217;s add our Link model to the admin page. Create a new file in the links folder called &#8220;admin.py&#8221; and paste in this code:

</p>

<pre class="brush: js">from django.contrib import admin



from djangoblog.links.models import Link



class LinkAdmin(admin.ModelAdmin):

    pass



admin.site.register(Link, LinkAdmin)

</pre>

<p>Note that I haven&#8217;t customized anything here, but feel free to add some list_display options or filters for easier sorting in the Admin interface.

</p><p>Now, open up the admin.py file in your djangoblog folder and change it so that it matches this code:

</p>

<pre class="brush: js">from django.contrib import admin

from djangoblog.blog.models import Entry

from djangoblog.blog.admin import EntryAdmin



from djangoblog.links.models import Link

from djangoblog.links.admin import LinkAdmin



class AdminSite(admin.AdminSite):

    pass



site = AdminSite()

site.register(Entry, EntryAdmin)

site.register(Link, LinkAdmin)

</pre>

<p><br />

The last step is to let Django know about our new Links app, so open up your settings.py file and add &#8220;links&#8221; to your list of installed apps.

</p><p>Now run syncdb in the shell:

</p>

<pre class="brush: js">python manage.py syncdb

</pre>

<p>And you&#8217;ll see that Django has created the required database tables. Fire up the development server and refresh the admin page to see your new links model.



</p><p><br />

</p>

<a name="Building_a_Delicious_client"></a><h2> <span class="mw-headline">Building a Delicious client</span></h2>

<p>Having Django set up the backend is pretty cool, but we don&#8217;t actually want to administer our links &#8212; we want them to be automatically created when we bookmark something on Delicious.com.

</p><p>To do that we&#8217;re going to need to send our user name and password over to Delicious which will the return a list of our most recent bookmarks. Then we need to parse through the XML, grab the data we need and store it in our new Link model.

</p><p>It might sound very complex, but it really isn&#8217;t, and once you have it set up you&#8217;ll never have to bother with it again, so let&#8217;s get started.

</p><p>What we need is a very simple client program to interact with Delicious.com. Luckily, there is a <a href="http://nixbit.com/cat/internet/nttp-%28www%29/delicious-python/" class="external text" title="http://nixbit.com/cat/internet/nttp-(www)/delicious-python/" rel="nofollow">Python library</a> that does just that. However, I find its dependancies make it more of a hassle than it needs to be. So I wrote my own client, which is dead simple, lacks many features of the other, but works for our purposes.

</p><p>Now you might be wondering, where should we store this? There isn&#8217;t a hard and fast rule that I know of, but I generally stick these sorts of things in the &#8220;utils.py&#8221; file within my app. So, create a new file in the links directory and name it utils.py.

</p><p>Here&#8217;s the code (which was sort of mashed up from several sources):

</p>

<pre class="brush: js">import urllib

import time

import dateutil.parser

import dateutil.tz

import xml.etree.cElementTree as xml_parser

from django.utils.encoding import smart_unicode



from djangoblog.links.models import Link



class DeliciousClient(object):

    interval = 0



    def __init__(self, username, password):

        self.username, self.password = username, password



    def fetch(self, **params):

        delta = time.time() - DeliciousClient.interval

        if delta &lt; 2:

            time.sleep(2 - delta)

        DeliciousClient.interval = time.time()

        url = 'https://%s:%s@api.del.icio.us/v1/posts/recent'&nbsp;% (self.username, self.password)

        return self.fetch_xml(url)



    def fetch_xml(self, url):

        u = urllib.FancyURLopener(None)

        usock = u.open(url)

        rawdata = usock.read()

        usock.close()

        return xml_parser.fromstring(rawdata)





    def __getattr__(self, method):

        return DeliciousClient(self.username, self.password, '%s/%s'&nbsp;% (self.method, method))



    def __repr__(self):

        return "&lt;DeliciousClient&gt;"





def create_link(data):

    for post in data.findall('post'):

        info = dict((k, smart_unicode(post.get(k))) for k in post.keys())

        b, created = Link.objects.get_or_create(

            url = info['href'],

            description = info['extended'],

            tags = info.get('tag', ''),

            date = parsedate(info['time']),

            title = info['description']

        )





def parsedate(s):

	dt = dateutil.parser.parse(s)

	if dt.tzinfo:

	    dt = dt.astimezone(dateutil.tz.tzlocal()).replace(tzinfo=None)

	return dt



</pre>

<p>There are many ways we could do this. Granted, my particular take is not the best, but I wanted to avoid dependancies, which this does. The only exception is that the ElementTree library is only present starting in Python 2.5. If you&#8217;re using an earlier version you&#8217;ll need to download and install ElementTree separately if you want to use this code.

</p><p>So what&#8217;s going on here? Well we have a class <code>DeliciousClient</code> which then has several methods. The main method of importance is &#8220;fetch,&#8221; which, when called, will return an ElementTree object with the 15 most recent links from our Delicious account.

</p><p>One thing to note: one of the rules of the Delicious API is that you can&#8217;t ping it more frequently than once per second. The code at the top of the <code>fetch</code> function ensures that we don&#8217;t exceed that limit.

</p><p>After the class, we have a small helper function that simply loops through the returned ElementTree object, pulls out the data nodes we need and then creates a new link in our database if one doesn&#8217;t already exist.

</p><p>The last function is just a generic date parser that converts a string into a date object, since that&#8217;s what our Django model is looking for.

</p>

<a name="Using_our_new_client"></a><h2> <span class="mw-headline">Using our new client</span></h2>

<p>So how does it work? Well, in order to demonstrate this app and run it on your own site, you&#8217;ll need to have a Delicious account with some links in it. So once you&#8217;re set up, follow along and get ready to import some links.



</p><p>Fire up your terminal and start the Django python client:

</p>

<pre class="brush: js">djangoblog sng$ python manage.py shell

</pre>

<p>Now let&#8217;s import our new tools and put them to use:

</p>

<pre class="brush: js">&gt;&gt;&gt; from djangoblog.links import utils

&gt;&gt;&gt; client = utils.DeliciousClient('username','passwd')

</pre>

<p>OK, now it&#8217;s time to fetch the data and save it to the database:

</p>

<pre class="brush: js">&gt;&gt;&gt; data = client.fetch()

&gt;&gt;&gt; utils.create_link(data)



</pre>

<p>With any luck, your fifteen most recent Delicious links should now be visible in the admin section. Start the dev server and refresh the page.

</p>

<a name="It.27s_all_in_the_timing"></a><h2> <span class="mw-headline">It&#8217;s all in the timing</span></h2>

<p>So far, we&#8217;re feeling pretty proud of ourselves. But we don&#8217;t want to have to log in to the shell every time we want to update our displayed list of bookmarks. In fact, we want our site to automatically update itself. To do that, we&#8217;re going to write a quick python script and then run it through a cron job.

</p><p>The only problem with that solution is that cron will run our script through the normal python interpreter which isn&#8217;t aware of our Django settings file and the like. Now worries though &#8212; we just need to tell it about it.

</p><p>Create a new file named sync_link.py and paste in this code:

</p>

<pre class="brush: js">import sys, os



sys.path.append('/path/to/django')

sys.path.append('/path/to/djangoblog')

os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoblog.settings'



from djangoblog.links import utils

client = utils.DeliciousClient('username','passwd')

data = client.fetch()

utils.create_link(data)

</pre>

<p>Now open your crontab and create a new entry that reads:

</p>

<pre class="brush: js">0,15,30,45 * * * * /path/to/python2.5 /path/to/sync_links.py 2&gt;&amp;1

</pre>



<p>That script will update your site with a new list every fifteen minutes. Naturally, you can adjust that list to suit your needs. If you&#8217;re a less-active bookmarker, once or twice per day should be sufficient.

</p><p><br />

</p>

<a name="Displaying_links"></a><h2> <span class="mw-headline">Displaying links</span></h2>

<p>To keep things simple, we&#8217;re not going to create permalink pages for our Delicious posts. If you&#8217;d like to do that, refer back to lesson 3, <a href="/2010/02/Use_URL_Patterns_and_Views_in_Django" class="external text" title="/2010/02/Use_URL_Patterns_and_Views_in_Django" rel="nofollow">Use URL Patterns and Views in Django</a>.

</p><p>Instead, we&#8217;ll just put our links in the sidebar of our blog. Open up the base.html template and add this code in the sidebar section:

</p>

<pre class="brush: js">&lt;h3&gt;Recent Delicious Links&lt;/h3&gt;

{% get_latest links.Link 5 as recent_links&nbsp;%}



&lt;ul class="archive"&gt;

	{% for obj in recent_links&nbsp;%}

	&lt;li&gt;

		&lt;a href="{{ obj.url }}" title="{{ obj.title}}"&gt;{{ obj.title}}&lt;/a&gt;{{obj.description}} Posted on {{obj.pub_date|date:"D d M Y"}}

	&lt;/li&gt;

	{% endfor&nbsp;%}



&lt;/ul&gt;

</pre>

<p>See, I told you that template tag would come in handy! We&#8217;ve used the very same template tag we <a href="/2010/02/Use_Templates_in_Django#Roll_your_own_template_tags" class="external text" title="/2010/02/Use_Templates_in_Django#Roll_your_own_template_tags" rel="nofollow">created in the last lesson to show recent blog entries</a> to display the links. Very nice.

</p>

<a name="Conclusion"></a><h2> <span class="mw-headline">Conclusion</span></h2>

<p>And there you have it, we&#8217;ve successfully integrated delicious into our blog. Hopefully, we&#8217;ve also shown how you might do something similar with other web services as well &#8212; Flickr, Twitter, Yelp, or anything with an API, really.

</p><p>Keep in mind that our Delicious client is just a quick and dirty hack. There are a number of ways you could improve it, such as adding functionality to check for updates to links that already exist. Or perhaps even abstract it some more so that it interacts with any of the many other Delicious API methods. The limits are&#8230; limitless.

</p><p>In the final installment of our Django Tutorial, we&#8217;ll set up our blog with a &#8220;river&#8221; of links and posts &#8212; a riff on the model popularized by FriendFeed and Tumblr &#8212; and add some RSS so people can subscribe to the streams of awesome content sure to follow.

</p><p>See you then.

</p>

<div id="series">



<div class="series_hdr">From the Django Tutorial series</div>

<table style="background: rgb(229, 249, 255) none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" width="620">

<tbody><tr>

<td>

<p><a href="/2010/02/Get_Started_With_Django" title="Tutorial:Get Started With Django"> Lesson 1: Get Started With Django</a><br />

<a href="/2010/02/Install_Django_and_Build_Your_First_App" title="Tutorial:Install Django and Build Your First App"> Lesson 2: Install Django and Build Your First App</a><br />

<a href="/2010/02/Use_URL_Patterns_and_Views_in_Django" title="Tutorial:Use URL Patterns and Views in Django"> Lesson 3: Use URL Patterns and Views in Django</a><br />

<a href="/2010/02/Use_Templates_in_Django" title="Tutorial:Use Templates in Django"> Lesson 4: User Templates in Django</a><br />



<strong class="selflink"> Lesson 5: Use Web API Data in Django</strong><br />

<a href="/2010/02/Build_a_Microblog_with_Django" title="Tutorial:Build a Microblog with Django"> Lesson 6: Build a Microblog with Django</a>

</p>

</td></tr></tbody></table>

</div><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/integrate_web_apis_into_your_django_site/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    
    <item>
        <title>Build a Microblog with Django</title>
        <link>http://www.webmonkey.com/2010/02/build_a_microblog_with_django/</link>
        <comments>http://www.webmonkey.com/2010/02/build_a_microblog_with_django/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=931</guid>
        		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[Thus far in our introductory Django tutorial, we&#8217;ve installed the open-source Django framework, set up a blog and beefed it up by adding some extras like semantic content tags, some handy template tags and a list of our bookmarks from delicious.com. If you haven&#8217;t been following along, now would be a good time to go [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>Thus far in our introductory Django tutorial, we&#8217;ve <a href="/2010/02/Install_Django_and_Build_Your_First_App" title="Tutorial:Install Django and Build Your First App"> installed the open-source Django framework</a>, set up a blog and beefed it up by adding some extras like <a href="/2010/02/Use_URL_Patterns_and_Views_in_Django" title="Tutorial:Use URL Patterns and Views in Django"> semantic content tags</a>, some handy <a href="/2010/02/Use_Templates_in_Django" title="Tutorial:Use Templates in Django"> template tags</a> and <a href="/2010/02/Integrate_Web_APIs_into_Your_Django_Site" title="Tutorial:Integrate Web APIs into Your Django Site"> a list of our bookmarks from delicious.com</a>. If you haven&#8217;t been following along, now would be a good time to go back to <a href="/2010/02/Get_Started_With_Django" title="Tutorial:Get Started With Django"> Lesson 1</a> and catch up.



</p><p>However, what we&#8217;ve created is not much different than what one could do with WordPress or another out-of-the-box blogging tool. That&#8217;s OK for a learning project. But now we&#8217;re getting close to being experts, we are going to explore some territory beyond what we can do with pre-built tools.

</p><p>Let&#8217;s build something a little more advanced. Let&#8217;s build a microblog.

</p><span id="more-931"></span>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>

<ol>

<li><a href="#Let.27s_get_ready_to_Tumble">Let&#8217;s get ready to Tumble</a></li>



<li><a href="#Laying_the_groundwork">Laying the groundwork</a></li>

<li><a href="#How_it_works">How it works</a></li>

<li><a href="#Listen_for_the_Signals">Listen for the Signals</a></li>

<li><a href="#Writing_the_URLs_and_views">Writing the URLs and views</a></li>

<li><a href="#Where_do_we_go_from_here.3F">Where do we go from here?</a></li>



<li><a href="#RSS_feeds">RSS feeds</a></li>

<li><a href="#Conclusion">Conclusion</a></li>

</ol>

</td></tr></tbody></table>



<a name="Let.27s_get_ready_to_Tumble"></a><h2> <span class="mw-headline">Let&#8217;s get ready to Tumble</span></h2>

<p>These days, many of us follow our friends on services like FriendFeed or Facebook, where the concept of a &#8220;blog post&#8221; is much looser, smaller and faster.

</p><p>Whether you want to call it a newsfeed, lifestream, microblog, tumblelog or a dozen other clever portmanteaus or neologisms, the concept is the same: a site to log snippets of your life and its discoveries in one place.

</p><p>FriendFeed is a favorite. The service combines tweets from Twitter, photos from Flickr, links from Delicious, updates from Facebook and other sundry data and displays them all on one page. The page itself also has an RSS feed, giving you (or any of your many fans) a way to follow your every move.



</p><p>Let&#8217;s build a version of Friendfeed using Django.  We&#8217;ll build a page displaying both our links and blog posts together in a single, time-based &#8220;river.&#8221; As a bonus we&#8217;ll add in some RSS sugar so our friends can follow along without having to visit the site.

</p>

<a name="Laying_the_groundwork"></a><h2> <span class="mw-headline"> Laying the groundwork </span></h2>

<p>Before we get started, let&#8217;s think for a bit about what needs to be done. We will post data two separate using two models: the blog Entry model and the Link model. We need to query them both at the same time and then sort the feed into reverse chronological order.

</p><p>The key to making it work is by creating a way to normalize our data. The database table for each of these models are significantly different. Instead of querying both models, wouldn&#8217;t it be better if we just query against one table?

</p><p>Let&#8217;s do it.

</p>

<a name="How_it_works"></a><h2> <span class="mw-headline"> How it works </span></h2>

<p>There&#8217;s one thing all models will have in common: a publication date. What we&#8217;re going to do is create a kind of meta model which stores the date as well as what kind of data it is (i.e. blog entry, link, etc).

</p><p>Django ships with two tools which actually make it very easy to build our meta model. The first is the <a href="http://www.djangoproject.com/documentation/contenttypes/" class="external text" title="http://www.djangoproject.com/documentation/contenttypes/" rel="nofollow">content types framework</a>. As the docs explain, &#8220;instances of ContentType represent and store information about the models installed in your project, and new instances of ContentType are automatically created whenever new models are installed.&#8221;



</p><p>Huh? Basically, what the Django Project is telling us is just by referencing the content type, we will always know what type of content we&#8217;re storing. Storing the content type is half the battle.

</p><p>The other half of the battle will be won by using a built-in field known as a <a href="http://www.djangoproject.com/documentation/contenttypes/#generic-relations" class="external text" title="http://www.djangoproject.com/documentation/contenttypes/#generic-relations" rel="nofollow">GenericForeignKey</a>. You may have noticed a ForeignKey field in the Django docs. ForeignKey is similar to what we&#8217;re going to use. Where ForeignKey refers to a single model, our GenericForeignKey can refer to any model by referencing the content_type instead.

</p><p>If that sounds confusing, don&#8217;t worry. It&#8217;ll make more sense when you see it in action.

</p><p>Let&#8217;s start writing some code. I&#8217;m going to store our meta app in a folder named &#8220;tumblelog&#8221; so create the folder and create a new <code>models.py</code> file inside it (don&#8217;t forget the <code>__init__.py</code> file as well, Python&#8217;s never-ending &#8220;gotcha&#8221;). Open up <code>models.py</code> in your text editor and paste in this code:

</p>

<pre class="brush: js">from django.db import models

from django.contrib.contenttypes import generic



class TumbleItem(models.Model):

    content_type = models.ForeignKey(ContentType)

    object_id = models.PositiveIntegerField()

    pub_date = models.DateTimeField()

    content_object = generic.GenericForeignKey('content_type', 'object_id')



    class Meta:

        ordering = ('-pub_date',)



    def __unicode__(self):

        return self.content_type.name





</pre>

<p>If you&#8217;re familiar with our previous tutorials (or Django in general), by now this should look somewhat familiar. We have a regular <code>ForeignKey</code> to the <code>ContentType</code> as we discussed above. Then we have an <code>id</code> field, which we need to pass to the <code>GenericForeignKey</code> field (along with <code>content_type</code>). Finally we add a <code>datetime</code> field for easy sorting. If you look at the <code>GenericForeignKey</code> documentation you&#8217;ll notice this is pretty much the same code used to demonstrate <code>GenericForeignKeys</code>. The only difference is we&#8217;ve added a <code>date</code> field.



</p><p>Now we have a basic script, but we certainly don&#8217;t want to update this by hand every time we post something. Especially since our delicious.com import script runs automatically.

</p><p>Well, it turns out there&#8217;s a very powerful feature baked into Django which can handle the task for us.

</p><p>Django includes an internal &#8220;dispatcher&#8221; which allows objects to listen for signals from other objects. In our case, our tumblelog app is going to &#8220;listen&#8221; to our Entry and Link models. Every time a new Entry or Link is saved, those models will send out a signal. When the tumblelog app gets the signal it will automatically update itself.

</p><p>Sweet. How do we do it?

</p>

<a name="Listen_for_the_Signals"></a><h2> <span class="mw-headline"> Listen for the Signals </span></h2>

<p>The first thing we need to do is import the signals framework. Add this to the top of your <code>model.py</code> file:

</p>

<pre class="brush: js">from django.db.models import signals

from django.contrib.contenttypes.models import ContentType

from django.dispatch import dispatcher

from blog.models import Entry

from links.models import Link

</pre>

<p>OK, now move to the bottom of the file and add these lines:



</p>

<pre class="brush: js">for modelname in [Entry, Link]:

	dispatcher.connect(create_tumble_item, signal=signals.post_save, sender=modelname)



</pre>

<p>In Django 1.1 (and 1.0 I think) the signal have changed.

Change the import to:

</p>

<pre class="brush: js">from django.db.models import signals

from django.contrib.contenttypes.models import ContentType

from django.db.models.signals import post_save

from blog.models import Entry

from links.models import Link

</pre>

<p>and change the dispatcher line to

</p>

<pre class="brush: js">post_save.connect(create_tweet_item, sender=Entry)

post_save.connect(create_tweet_item, sender=Link)

</pre>

<p><br />

</p><p><br />

So what&#8217;s it do? Well it tells the dispatcher to listen for the <code>post_save</code> signal from out Entry and Link models and whenever it gets the signal, it will fire off our <code>create_tumble_item</code> function.



</p><p>But wait, we don&#8217;t have a <code>create_tumble_item</code> function do we?

</p><p>No, so we better write one. Just above the <code>dispatcher</code> function add this code:

</p>

<pre class="brush: js">def create_tumble_item(sender, instance, signal, *args, **kwargs):

	if 'created' in kwargs:

		if kwargs['created']:

			create = True

			ctype = ContentType.objects.get_for_model(instance)

			if ctype.name == 'link':

				pub_date = instance.date

			else:

				pub_date = instance.pub_date

			if create:

				t = TumbleItem.objects.get_or_create(content_type=ctype, object_id=instance.id, pub_date=pub_date)

</pre>

<p>What&#8217;s this function doing? For the most part it&#8217;s just taking the data sent by the dispatcher and using it to create a new <code>TumbleItem</code>.

</p><p>The first line looks to see if a variable, <code>created</code>, has been passed by the dispatcher. The <code>post_save</code> signal is sent everytime an object is saved, so it&#8217;s possible we&#8217;ve just updated an existing item rather than creating a new one. In that case, we don&#8217;t want to create a new <code>TumbleItem</code>, so the function checks to make sure this is, in fact, a new object.



</p><p>If the dispatcher has passed the variable <code>created</code>, and its true, then we set our own <code>create</code> flag and get the <code>content_type</code> of the passed instance. This way, we know whether it&#8217;s a Link or an Entry.

</p><p>If it&#8217;s a Link we need to find the datetime info. When we built our Link model, we called the field <code>date</code>, so we set our normalizing <code>pub_date</code> field equal to the <code>instance.date</code> field.



</p><p>If the instance is a blog Entry we set <code>pub_date</code> to the value of the instance&#8217;s <code>pub_date</code> field since, it shares the name we used in our Entry model.

</p><p>Then we create a new TumbleItem using the built-in <code>get_or_create</code> method. We also pass in a <code>content_type</code>, <code>id</code> and <code>pub_date&lt;code&gt; to their respective fields.



</code></p><p>And there you have it. Any time you create a blog entry or the script adds a new link, our new TumbleItem model will automatically update.

</p><p>There&#8217;s a slight problem though. What about the data we&#8217;ve already got in there?

</p><p>Well to make sure it gets added, we&#8217;re going to have to comment out the following lines:

</p>

<pre class="brush: js">	if 'created' in kwargs:

		if kwargs['created']:

</pre>

<p>Comment it out and save the file. Then fire up the terminal and enter this code one line at a time:

</p>

<pre class="brush: js">&gt;&gt;&gt; from blog.models import Entry

&gt;&gt;&gt; from link.models import Link

&gt;&gt;&gt; entries = Entry.objects.all()

&gt;&gt;&gt; for entry in entries:

...     entry.save()

...



&gt;&gt;&gt; links = Link.objects.all()

&gt;&gt;&gt; for link in Link:

...     link.save()

...

&gt;&gt;&gt;

</pre>

<p>What did it do? We just called the &lt;code&gt;save method and dispatcher passed its signal along to the TumbleItem model which then updated itself. Because we commented out the lines that check to see if an item is new, the function ran regardless of the instance&#8217;s created variable.

</p><p>Now uncomment those lines and save the file.

</p><p>Before we move on I should point out <code>post_save</code> isn&#8217;t the only signal Django can send. There are in fact a whole bunch of useful signals like <code>request_started</code>, <code>pre_save</code> and many more. Check out the <a href="http://code.djangoproject.com/wiki/Signals" class="external text" title="http://code.djangoproject.com/wiki/Signals" rel="nofollow">Django wiki</a> for more details.



</p><p><br />

</p>

<a name="Writing_the_URLs_and_views"></a><h2> <span class="mw-headline"> Writing the URLs and views </span></h2>

<p>Now we need to add a tumblelog URL and pull out the data. Open up your project level <code>urls.py</code> file and add this line:

</p>

<pre class="brush: js">(r'^tumblelog/', 'tumblelog.views.tumbler'),

</pre>

<p>Now create a new <code>views.py</code> file inside your tumblelog folder and open it up to paste in this code:



</p>

<pre class="brush: js">from tumblelog.models import TumbleItem

from django.shortcuts import render_to_response



def tumbler(request):

	context = {

		'tumble_item_list': TumbleItem.objects.all().order_by('-pub_date')

	}



	return render_to_response('tumblelog/list.html', context)

</pre>

<p>What&#8217;s going on here? Well first we grab the tumblelog items and then we use a Django shortcut function to return to pass the list on to template named <code>list.html</code>.

</p><p>Let&#8217;s create the template. Add a new folder &#8220;tumblelog&#8221; inside your templates folder and create the <code>list.html</code> file. We&#8217;ll start by extending our base template and filling in the blocks we created in <a href="/2010/02/Use_Templates_in_Django" title="Tutorial:Use Templates in Django"> an earlier lesson</a>:

</p>

<pre class="brush: js">{% block title&nbsp;%}My Tumblelog{% endblock&nbsp;%}

{% block primary&nbsp;%}

{% for object in object_list&nbsp;%}

	{%if object 'link'%}

		&lt;a href="{{ obj.url }}" title="{{ obj.title}}"&gt;{{ obj.title}}&lt;/a&gt;{{object.description}} Posted on {{object.pub_date|date:"D d M Y"}}

	{% endif&nbsp;%}



	{%if object 'entry'%}

		&lt;h2&gt;{{ object.title }}&lt;/h2&gt;



		&lt;p&gt;{{ object.pub_date }}&lt;/p&gt;

		{{ object.body_html|truncatewords_html:"20"|safe }}

		&lt;p&gt;&lt;a href="{{object.get_absolute_url}}"&gt;more&lt;/a&gt;&lt;/p&gt;

	{% endif&nbsp;%}

{% endfor&nbsp;%}

{% endblock&nbsp;%}



</pre>

<p>If you start up the development server and head to <a href="http://127.0.0.1:8000/tumblelog/" class="external free" title="http://127.0.0.1:8000/tumblelog/" rel="nofollow">http://127.0.0.1:8000/tumblelog/</a> you should see your blog entries and links ordered by date.

</p>

<a name="Where_do_we_go_from_here.3F"></a><h2> <span class="mw-headline"> Where do we go from here? </span></h2>

<p>We&#8217;re looking pretty good up until we get to the template stage. The <code>if</code> statements aren&#8217;t so bad when we&#8217;re only sorting two content types, but if you start pulling in tons of different types of data you&#8217;ll quickly end up with spaghetti code.

</p><p>A far better idea would be to write a template tag which takes the <code>content type</code> as an argument, uses it to call a template file, renders it and passes back to the html as a string.



</p><p>We&#8217;ll leave it up to you as an exercise (hint: read up on Django&#8217;s <a href="http://www.djangoproject.com/documentation/templates_python/#the-render-to-string-shortcut" class="external text" title="http://www.djangoproject.com/documentation/templates_python/#the-render-to-string-shortcut" rel="nofollow">render_to_string method</a>).

</p><p>The other thing you might be wondering about is pagination. If you save dozens of links a day and blog like a madman, this page is going to get really large really fast. Django ships with some built-in pagination tools (see <a href="http://www.djangoproject.com/documentation/pagination/" class="external text" title="http://www.djangoproject.com/documentation/pagination/" rel="nofollow">the docs</a>) and there&#8217;s also a slick <a href="http://code.google.com/p/django-pagination/" class="external text" title="http://code.google.com/p/django-pagination/" rel="nofollow">django-pagination app</a> available from Eric Florenzano. Eric even has a <a href="http://eflorenzano.com/blog/post/first-two-django-screencasts/#using-django-pagination" class="external text" title="http://eflorenzano.com/blog/post/first-two-django-screencasts/#using-django-pagination" rel="nofollow">very nice screencast</a> on how to set things up.

</p><p><br />

</p>

<a name="RSS_feeds"></a><h2> <span class="mw-headline"> RSS feeds </span></h2>



<p>We&#8217;re almost done. Let&#8217;s hook up some RSS feeds for our new site.

</p><p>It turns out, Django ships with a very nice <a href="http://www.djangoproject.com/documentation/syndication_feeds/" class="external text" title="http://www.djangoproject.com/documentation/syndication_feeds/" rel="nofollow">syndication framework</a>. All we need to do is turn it on and hook it up.

</p><p>Let&#8217;s start by going into our TumbleItem <code>models.py</code> file and setting up the framework. Paste in this code at the bottom of the file:

</p>

<pre class="brush: js">from django.contrib.syndication.feeds import Feed

class LatestItems(Feed):

    title = "My Tumblelog: Links"

    link = "/tumblelog/"

    description = "Latest Items posted to mysite.com"

    description_template = 'feeds/description.html'



    def items(self):

        return TumbleItems.objects.all.order_by('-pub_date')[:10]



</pre>

<p>Here we&#8217;ve imported the syndication class <code>Feed</code> and then defined our own feed class to fill in some basic data. The last step is returning the items using a normal <code>objects</code> query.



</p><p>We need to create the URLs first. There are several places you could do this, I generally opt for the main project URLs.py file. Open it up and paste this code just below the other import statements:

</p>

<pre class="brush: js">from tumblelog.models import LatestItems

feeds = {

    'tumblelog': LatestItems

}

</pre>

<p>Now add this line to your <code>urlpattern</code> function:

</p>

<pre class="brush: js">(r'^feeds/(?P&lt;url&gt;.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),

</pre>

<p>The last step is creating the description template in a new folder we&#8217;ll lable &#8220;feeds.&#8221; Just plug in the same code from the tumblelog template, but delete the <code>forloop</code> tag since we&#8217;re only passing a single object this time.



</p><p>And there you have it. Fire up the development server and point it to <a href="http://127.0.0.1:8000/feeds/tumblelog/" class="external free" title="http://127.0.0.1:8000/feeds/tumblelog/" rel="nofollow">http://127.0.0.1:8000/feeds/tumblelog/</a>. If you want to add separate feeds for links or just blog entries, all you need to do is repeat the process, creating new <code>feed</code> classes for each.

</p>

<a name="Conclusion"></a><h2> <span class="mw-headline"> Conclusion </span></h2>

<p>Whew! It&#8217;s been a long journey and we wrote a lot of code, but hopefully you learned a good bit about how Django works. You not only have a blog/linklog/tumblelog, but hopefully some ideas of how to approach other projects.

</p><p>Speaking of projects, although we used one, there&#8217;s really no need to organize your code this way. Sometimes the projects come in handy, but other times they make your PYTHONPATH into a snarled mess. For some other ideas on how organize you code, check out James Bennet&#8217;s <a href="http://www.b-list.org/weblog/2007/nov/09/projects/" class="external text" title="http://www.b-list.org/weblog/2007/nov/09/projects/" rel="nofollow">article on the subject</a>.

</p><p>If you ever have questions about Django, jump on the <a href="irc://irc.freenode.net/django" class="external text" title="irc://irc.freenode.net/django" rel="nofollow">#Django IRC channel</a>, there&#8217;s load of friendly and helpful developers who can point you in the right direction, and be sure to <a href="http://groups.google.com/group/django-users" class="external text" title="http://groups.google.com/group/django-users" rel="nofollow">join the mailing list</a>. Happy coding!



</p>

<div id="series">

<div class="series_hdr">From the Django Tutorial series</div>

<table style="background: rgb(229, 249, 255) none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" width="620">

<tbody><tr>

<td>

<p><a href="/2010/02/Get_Started_With_Django" title="Tutorial:Get Started With Django"> Lesson 1: Get Started With Django</a><br />

<a href="/2010/02/Install_Django_and_Build_Your_First_App" title="Tutorial:Install Django and Build Your First App"> Lesson 2: Install Django and Build Your First App</a><br />

<a href="/2010/02/Use_URL_Patterns_and_Views_in_Django" title="Tutorial:Use URL Patterns and Views in Django"> Lesson 3: Use URL Patterns and Views in Django</a><br />

<a href="/2010/02/Use_Templates_in_Django" title="Tutorial:Use Templates in Django"> Lesson 4: User Templates in Django</a><br />



<a href="/2010/02/Integrate_Web_APIs_into_Your_Django_Site" title="Tutorial:Integrate Web APIs into Your Django Site"> Lesson 5: Use Web API Data in Django</a><br />

<strong class="selflink"> Lesson 6: Build a Microblog with Django</strong>

</p>

</td></tr></tbody></table>

</div><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/build_a_microblog_with_django/feed/</wfw:commentRss>
        <slash:comments>2</slash:comments>

        
    </item>
    
    <item>
        <title>Django 1.2 Alpha Offers Multiple Database Support, Improved Security Features</title>
        <link>http://www.webmonkey.com/2010/01/django_1dot2/</link>
        <comments>http://www.webmonkey.com/2010/01/django_1dot2/#comments</comments>
        <pubDate>Fri, 08 Jan 2010 12:46:25 +0000</pubDate>

                <dc:creator>Scott Gilbertson</dc:creator>

        <guid isPermaLink="false">http://www.webmonkey.com/blog/django12alphaoffersmultipledatabasesupportimprovedsecurityfeatures</guid>
        		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[Security]]></category>
        <description><![CDATA[Django, the popular web development framework written in Python, has released the first alpha for its much-anticipated new version, Django 1.2. Among the new features coming in Django 1.2 are support for multiple databases &#8212; a key feature for larger websites running Django &#8212; improved security features and a messaging framework that works much like [...]]]></description>

            <content:encoded><![CDATA[<p><!-- wpautop enabled --><img class="blogimg" src="http://www.wired.com/images_blogs/epicenter/2009/07/django-folder.jpg" /><a href="http://www.djangoproject.com/">Django</a>, the popular web development framework written in Python, has released the first alpha for its much-anticipated new version, Django 1.2.</p>
<p>Among the new features <a href="http://docs.djangoproject.com/en/dev/releases/1.2-alpha-1/#what-s-new-in-django-1-2-alpha-1">coming in Django 1.2</a> are support for multiple databases &#8212; a key feature for larger websites running Django &#8212; improved security features and a messaging framework that works much like Ruby on Rail&#8217;s &#8220;flash&#8221; feature.</p>
<p>The multiple database support will likely be the most important part of the next version of Django since it will allow for much easier application scaling. Django 1.2 makes it easy to target individual databases within your apps using some new queryset methods which make it easy to read and write to specific databases.</p>
<p>The security features include much-improved protection against Cross-Site Request Forgery (CSRF) attacks. For more details on how the CSRF protection works, have a look at the <a href="http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ref-contrib-csrf">new CSRF documentation page</a>.</p>
<p>If you&#8217;d like to test out Django 1.2, or see how your apps run on the new release, head over to the <a href="http://www.djangoproject.com/download/">downloads page</a> or update your Subversion checkout. Keep in mind though that this is still an alpha release and should not be used on production sites. The final release of Django 1.2 is <a href="http://code.djangoproject.com/wiki/Version1.2Roadmap">scheduled to arrive in March 2010</a>.</p>
<p><strong>See Also:</strong></p>
<ul>
<li><a href="http://www.webmonkey.com/blog/Flush_With_Choices__Developers_Still_Dig_Django_the_Most">Flush With Choices, Developers Still Dig Django the Most</a></li>
<li><a href="http://www.webmonkey.com/blog/Latest_Django_Beta_Sets_the_Stage_for_1DOT0_Release">Latest Django Beta Sets the Stage for 1.0 Release</a></li>
<li><a href="/2010/02/Get_Started_With_Django">Get Started With Django</a></li>
</ul>
<div id='linker_widget' class='contextly-widget'></div>
]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/01/django_1dot2/feed/</wfw:commentRss>
        <slash:comments>1</slash:comments>

        
    </item>
    
    <item>
        <title>User-Contributed Announcements Give EveryBlock a Human Touch</title>
        <link>http://www.webmonkey.com/2010/01/user-contributed_announcements_give_everyblock_a_human_touch/</link>
        <comments>http://www.webmonkey.com/2010/01/user-contributed_announcements_give_everyblock_a_human_touch/#comments</comments>
        <pubDate>Fri, 08 Jan 2010 12:24:15 +0000</pubDate>

                <dc:creator>Scott Gilbertson</dc:creator>

        <guid isPermaLink="false">http://www.webmonkey.com/blog/usercontributedannouncementsgiveeveryblockahumantouch</guid>
        		<category><![CDATA[Location]]></category>
		<category><![CDATA[Social]]></category>
		<category><![CDATA[Web Apps]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[EveryBlock]]></category>
		<category><![CDATA[geolocation]]></category>
        <description><![CDATA[EveryBlock, the local news aggregator that shows you block-level details about your city, has added a new feature dubbed, &#8220;Notify your neighbors,&#8221; which allows anyone in your neighborhood to post news on the site. EveryBlock, which launched in 2008, touts itself as &#8220;a geographic filter&#8221; for your city or your neighborhood. The site crawls local [...]]]></description>

            <content:encoded><![CDATA[<p><!-- wpautop enabled --><img class="blogimg" src="http://howto.wired.com/mediawiki/images/Everyblockcat.jpg" /></p>
<p>EveryBlock, the local news aggregator that shows you block-level details about your city, has added a new feature dubbed, &#8220;<a href="http://blog.everyblock.com/2010/jan/07/notifyyourneighbors/">Notify your neighbors</a>,&#8221; which allows anyone in your neighborhood to post news on the site.</p>
<p><a href="http://www.everyblock.com/">EveryBlock</a>, which <a href="http://www.webmonkey.com/blog/EveryBlock_Launches_Hyper-local_News_Service_for_Big_Cities">launched in 2008</a>, touts itself as &#8220;a geographic filter&#8221; for your city or your neighborhood. The site crawls local newspapers, radio and television stations as well as local blogs, independent media sources and government data feeds to show you what&#8217;s happening on your block. At the moment EveryBlock serves fifteen U.S. cities, though the site is always taking suggestions for more.</p>
<p>While EveryBlock pulls in an impressive amount of data, it can&#8217;t hope to find everything about your block &#8212; for example, a private neighborhood listserv or other very small, self-organized neighborhood websites are either off limits or simply too numerous to crawl.</p>
<p>The new Notify feature is, in part, designed to overcome that by allowing you to post your own events, news and, well, anything really.</p>
<p>The EveryBlock blog calls the new feature &#8220;intentionally open-ended,&#8221; and is hoping that users will come up with novel ways to use it. Early beta previews were made available to select users who used Notify to do everything from post lost pet messages to chatting about <a href="http://sf.everyblock.com/announcements/by-date/2009/11/30/2838776/">howling cats</a> and missing mailboxes (damn kids!).</p>
<p>The new feature is also part of the <a href="http://www.webmonkey.com/blog/EveryBlock_Brings_Hyperlocal_News_to_the_iPhone">EveryBlock iPhone app</a>, so you can post announcements as you walk down the street.</p>
<p>Within the site, user-generated posts are labeled as &#8220;announcements&#8221; and link back to the poster&#8217;s profile (so yes, you need to sign up before you can post).</p>
<p>So far the feature looks very useful and gives EveryBlock a human touch that sometimes felt missing in early incarnations. Whether or not it will help build a community or end up being overrun with spam remains to be seen.</p>
<p><strong>See Also:</strong></p>
<ul>
<li><a href="http://www.webmonkey.com/blog/EveryBlock_Source_Code_Release_Offers_Glimpse_of_the_Magic_Behind_the_Curtain">EveryBlock Source Code Release Offers Glimpse of the Magic Behind the Curtain</a></li>
<li><a href="http://www.webmonkey.com/blog/EveryBlock_Launches_Hyper-local_News_Service_for_Big_Cities">EveryBlock Launches Hyper-local News Service for Big Cities</a></li>
<li><a href="http://www.webmonkey.com/blog/EveryBlock_Brings_Hyperlocal_News_to_the_iPhone">EveryBlock Brings Hyperlocal News to the iPhone</a></li>
</ul>
<div id='linker_widget' class='contextly-widget'></div>
]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/01/user-contributed_announcements_give_everyblock_a_human_touch/feed/</wfw:commentRss>
        <slash:comments>1</slash:comments>

        
    </item>
    
    <item>
        <title>Django Unveils 1.1 Roadmap</title>
        <link>http://www.webmonkey.com/2008/09/django_unveils_1dot1_roadmap/</link>
        <comments>http://www.webmonkey.com/2008/09/django_unveils_1dot1_roadmap/#comments</comments>
        <pubDate>Mon, 22 Sep 2008 14:37:05 +0000</pubDate>

                <dc:creator>Scott Gilbertson</dc:creator>

        <guid isPermaLink="false">http://www.webmonkey.com/blog/djangounveils11roadmap</guid>
        		<category><![CDATA[Software & Tools]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
        <description><![CDATA[As announced at the recent Django Conference, the web development for &#8220;perfectionists with deadlines,&#8221; is moving to a regular, timed release schedule. The full details of how Django releases and version numbers will work can be found in the project&#8217;s much improved documentation, but the real news is that Django 1.1 will arrive in March [...]]]></description>

            <content:encoded><![CDATA[<p><!-- wpautop enabled -->
<p><img class="blogimg" src="http://howto.wired.com/mediawiki/images/Django200px.jpg" alt="django folder" />As announced at the <a href="http://www.webmonkey.com/blog/Django_s_Creators_Discuss_the_Framework_s_Future">recent Django Conference</a>, the web development for <a href="http://djangoproject.com">&#8220;perfectionists with deadlines,&#8221;</a> is moving to a regular, timed release schedule. The full details of <a href="http://docs.djangoproject.com/en/dev/internals/release-process/">how Django releases and version numbers will work</a> can be found in the project&#8217;s much improved documentation, but the real news is that <a href="http://code.djangoproject.com/wiki/Version1.1Roadmap">Django 1.1 will arrive in March 2009</a>.</p>
<p>That means that if there&#8217;s something you&#8217;d like to see in Django 1.1, you need to make your proposal before November 7. Come November 15, we&#8217;ll get to see what the Django team will be working on for the next release. </p>
<p>Look for django 1.1 at arrive somewhere around March 16-20.</p>
<p>As outlined in the docs, all minor Django release (1.1, 1.2, etc) should be backwards compatible with earlier 1.x releases, so if you&#8217;re writing code for Django 1.0 you should be fine when the next minor version arrives.</p>
<p><strong>See Also:</strong><br/></p>
<ul>
<li><a href="http://www.webmonkey.com/blog/Django_s_Creators_Discuss_the_Framework_s_Future">Django&#8217;s Creators Discuss the Framework&#8217;s Future</a></li>
<li><a href="http://www.webmonkey.com/blog/Django_Deemed_Perfect__Goes_1DOT0">Django Deemed Perfect, Goes 1.0</a></li>
<li><a href="http://www.webmonkey.com/blog/Simplify_Django_Debugging_With_New_Toolbar">Simplify Django Debugging With New Toolbar</a></li>
</ul>
<div id='linker_widget' class='contextly-widget'></div>
]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2008/09/django_unveils_1dot1_roadmap/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    
    <item>
        <title>Simplify Django Debugging With New Toolbar</title>
        <link>http://www.webmonkey.com/2008/09/simplify_django_debugging_with_new_toolbar/</link>
        <comments>http://www.webmonkey.com/2008/09/simplify_django_debugging_with_new_toolbar/#comments</comments>
        <pubDate>Mon, 22 Sep 2008 00:05:40 +0000</pubDate>

                <dc:creator>Adam Duvander</dc:creator>

        <guid isPermaLink="false">http://www.webmonkey.com/blog/simplifydjangodebuggingwithnewtoolbar</guid>
        		<category><![CDATA[Programming]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[django]]></category>
        <description><![CDATA[Django developer Rob Hudson has built an extensible Django Debug Toolbar for viewing common information, such as HTTP headers and SQL queries. When installed and enabled, the toolbar takes up less than thirty pixels at the top of the screen. You can click one of the panels (there are currently seven available) and an overlay [...]]]></description>

            <content:encoded><![CDATA[<p><!-- wpautop enabled --><img class="blogimg" src="http://howto.wired.com/mediawiki/images/Django-toolbar.png" alt="Django toolbar in action" class="full" /></p>
<p>Django developer Rob Hudson has built an extensible <a href="http://rob.cogit8.org/blog/2008/Sep/19/introducing-django-debug-toolbar/">Django Debug Toolbar</a> for viewing common information, such as HTTP headers and SQL queries. When installed and enabled, the toolbar takes up less than thirty pixels at the top of the screen. You can click one of the panels (there are currently seven available) and an overlay opens for that panel.</p>
<p>The inspiration came from the <a href="http://www.symfony-project.org/">Symfony Project</a>, a PHP framework. Hudson announced his project after Cal Henderson showed something similar for Pownce at DjangoCon during Henderson&#8217;s <a href="http://www.webmonkey.com/blog/DjangoCon:_Flickr_s_Cal_Henderson_Hates_Django">Why I Hate Django</a> talk. Later, Hudson <a href="http://www.davidcramer.net/code/280/django-debug-toolbar.html">collaborated with fellow developer David Cramer</a>, so the toolbar grew out of the Django community.</p>
<p>One of the coolest things about the project is that each panel is separate. So, if you don&#8217;t want the one that shows the current version, you don&#8217;t have to include it. Even better, if it&#8217;s missing functionality you want, or there&#8217;s something specific to your project you want to show in the debug toolbar, you can write your own panel.</p>
<p>Unlike many of the toolbars we see, this one is not installed in the browser. It resides on the same server as your Django installation. It&#8217;s meant for developers, not end-users, so it only shows when it matches the IP addresses added to the INTERNAL_IPS Django setting.</p>
<p>[Screenshot by David Cramer]</p>
<p><strong>See also:</strong></p>
<ul>
<li><a href="http://www.webmonkey.com/blog/DjangoCon_Video_Coverage_Now_Online">DjangoCon Video Coverage Now Online</a></li>
<li><a href="http://www.webmonkey.com/blog/Django_Deemed_Perfect__Goes_1DOT0">Django Deemed Perfect, Goes 1.0</a></li>
<li><a href="/2010/02/Get_Started_With_Django">Tutorial: Get Started With Django </a></li>
</ul>
<div id='linker_widget' class='contextly-widget'></div>
]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2008/09/simplify_django_debugging_with_new_toolbar/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    </channel>
</rss>