<?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>Disqus &#187; Django</title>
	<atom:link href="http://blog.disqus.net/category/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.disqus.net</link>
	<description></description>
	<lastBuildDate>Tue, 22 Sep 2009 18:11:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MintCache (simple version)</title>
		<link>http://blog.disqus.net/2008/06/11/mintcache-simple-version/</link>
		<comments>http://blog.disqus.net/2008/06/11/mintcache-simple-version/#comments</comments>
		<pubDate>Wed, 11 Jun 2008 20:41:51 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[disqus]]></category>

		<guid isPermaLink="false">http://blog.disqus.net/?p=121</guid>
		<description><![CDATA[MintCache is a caching scheme Disqus has recently implemented. We posted Disqus&#8217; implementation of MintCache for others to use.
From the original MintCache posting:

The purpose of this caching scheme is to avoid the dog-pile effect. Dog-piling is what normally happens when your data for the cache takes more time to generate than your server is answering [...]]]></description>
			<content:encoded><![CDATA[<p>MintCache is a caching scheme Disqus has recently implemented. We posted <a href="http://www.djangosnippets.org/snippets/793/">Disqus&#8217; implementation of MintCache</a> for others to use.</p>
<p>From <a href="http://www.djangosnippets.org/snippets/155/">the original MintCache posting</a>:</p>
<blockquote><p>
The purpose of this caching scheme is to avoid the dog-pile effect. Dog-piling is what normally happens when your data for the cache takes more time to generate than your server is answering requests per second. In other words if your data takes 5 seconds to generate and you are serving 10 requests per second, then when the data expires the normal cache schemes will spawn 50 attempts a regenerating the data before the first request completes. The increased load from the 49 redundant processes may further increase the time it takes to generate the data. If this happens then you are well on your way into a death spiral</p>
<p>MintCache works to prevent this scenario by using memcached to to keep track of not just an expiration date, but also a stale date The first client to request data past the stale date is asked to refresh the data, while subsequent requests are given the stale but not-yet-expired data as if it were fresh, with the undertanding that it will get refreshed in a &#8216;reasonable&#8217; amount of time by that initial request.
</p></blockquote>
<p>Link: <a href="http://www.djangosnippets.org/snippets/793/">MintCache (simple version)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.disqus.net/2008/06/11/mintcache-simple-version/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>A Django Primer &#8211; Creating a Simple Blog Application</title>
		<link>http://blog.disqus.net/2007/03/11/a-django-primer/</link>
		<comments>http://blog.disqus.net/2007/03/11/a-django-primer/#comments</comments>
		<pubDate>Sun, 11 Mar 2007 21:10:34 +0000</pubDate>
		<dc:creator>Jason</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.bigheadlabs.com/?p=10</guid>
		<description><![CDATA[Preface
A couple of months ago, Daniel and I began drafting ideas for a new website.  When it came down to choosing a language to begin our work, we had a tough decision to make.  We both traditionally stuck to PHP for web development in the past, but we wanted to use a web [...]]]></description>
			<content:encoded><![CDATA[<h2>Preface</h2>
<p>A couple of months ago, Daniel and I began drafting ideas for a new website.  When it came down to choosing a language to begin our work, we had a tough decision to make.  We both traditionally stuck to PHP for web development in the past, but we wanted to use a web framework for rapid development.  The decision to use <a href="http://www.djangoproject.com/">Django</a> came from three things: it&#8217;s written in Python, there are proven real world examples of large-scale websites using Django (the developers kept performance in mind and implemented a nice caching framework), and the documentation is good.</p>
<p>While this primer will mainly aim at those with no Django experience (or experience with a web framework at all), I am assuming that you have some understanding of Python.  I will go over the details for creating a simple blog application.  While Django is still not at 1.0 yet (as of this writing), there are things which may change.  I will do my best to make sure to this information stays up to date.  I am also assuming you are using the latest development version (0.96-dev as of this writing).  Installation of the development version will require Subversion and is documented on the official Django project website <a href="http://www.djangoproject.com/documentation/install/">here</a>.</p>
<p><span id="more-10"></span></p>
<h2>Table of Contents</h2>
<ol>
<li><a href="#Introduction">Introduction</a></li>
<li><a href="#GettingStarted">Getting Started</a></li>
<li><a href="#Models">Models</a></li>
<li><a href="#AdminSite">The Admin Site</a></li>
<li><a href="#GenericViews">Generic Views and URLs</a></li>
<li><a href="#Templates">Templates</a></li>
<li><a href="#Conclusion">Conclusion</a></li>
</ol>
<p><a name="Introduction"></a><br />
<h2>Introduction</h2>
<p>Django adopts the standard MVC (Model-View-Controller) design pattern, but instead the acronym is a little bit different.  Instead, their naming convention is the MTV (Model-Template-View).  Essentially, your code will be broken up into three main components.  <strong>The model</strong> is an object relational mapping to your database schema.  So each model is a class which represents a table in your database.  This abstracts the underlying database management system and also generates the SQL statements based on the methods you call on your model.  This is attractive to those who are afraid of touching SQL as virtually little to no SQL knowledge is required by using Django&#8217;s model API.  <strong>The template</strong> is simply the HTML for your view (if you&#8217;ve used MVC web frameworks in the past, remember that a view is the controller in MVC).  If you have used PHP in the past, you may have mixed PHP code and HTML together, which in turn became a mess to look at and maintain.  In addition to HTML, Django&#8217;s template system allows you to use simple constructs for template-specific logic.  For instance, you could display different messages depending on whether or not a user is logged in.  <strong>The view</strong> can be thought of as a page in your application.  It could be the homepage or a page to display a user&#8217;s information, for instance.</p>
<p>This primer will guide you through creating a simple blog, which will be extended upon throughout this primer.  I will explain a concept, and then show an example of writing a blog application, but I encourage you to stray away from this if you have a different application you would like to implement.</p>
<p><a name="GettingStarted"></a><br />
<h2>Getting Started</h2>
<p>I am assuming you have already installed Python, Django, and the database management system of your choice (PostgreSQL is recommended).  Also, I will be using $PYTHON_DIR and $DJANGO_DIR as a shorthand for explaining the location of files.  For example, $PYTHON_DIR in my case is C:/Python25 and my $DJANGO_DIR is C:/Python25/lib/site-packages/django.</p>
<p>First, we&#8217;ll need to create our project.</p>
<ul>
<li>
<strong>NOTE</strong>: Depending on the method you&#8217;ve installed Django and the platform you&#8217;re on, you may need to first create a symlink to the django-admin.py script.  <strong>django-admin.py</strong> is located in $DJANGO_DIR/bin/django-admin.py.  In Windows, I created a batch script, django-admin.bat, which I placed in my $PYTHON_DIR since it is in my environment&#8217;s PATH variable.  The script is just:<br />
<code><br />
c:\python25\python.exe C:\Python25\lib\site-packages\django\bin\django-admin.py %1 %2 %3 %4 %5 %6 %7 %8 %9<br />
</code><br />
If you do end up using this batch script, run django-admin, <strong>not</strong> django-admin.py in all of the following examples.
</li>
</ul>
<p>To create your project, simply run <strong>django-admin.py startproject DjangoPrimer</strong>, where DjangoPrimer is the name of your project.  This will create a directory named DjangoPrimer in your current working directory with the following files:</p>
<ul>
<li><strong>__init__.py</strong> &#8212; Blank module to initialize the package (your Django project)</li>
<li><strong>manage.py</strong> &#8212; Wrapper to django-admin.py with your project&#8217;s settings module and project added to sys.path</li>
<li><strong>settings.py</strong> &#8212; Django settings for your project</li>
<li><strong>urls.py</strong> &#8212; URL <a href="http://en.wikipedia.org/wiki/Regular_expression">regular expression</a> mappings to views (this will be explained in greater detail shortly)</li>
</ul>
<p>We&#8217;ll start by creating our first application &#8212; our blog.  In the current working directory of your project, type <code>python manage.py startapp blog</code>.  This will generate a new folder called <b>blog</b> with stubs (empty placeholders) for your views and models.</p>
<p>Next, we&#8217;ll need to make a few modifications to settings.py.  I won&#8217;t be going through the entire file since <a href="http://www.djangoproject.com/documentation/settings/">the Django documentation for settings</a> does a thorough job of that.  Of interest to us are the database settings.  You need to choose the engine of the database management system you are running.  The <a href="http://www.djangoproject.com/documentation/install/#get-your-database-running">Django installation documentation</a> describes what you need to get your database running.  The changes I have made to settings.py are as follows:</p>
<ul>
<li>
  <b>Change the database settings to reflect your database</b><br />
  <code>DATABASE_ENGINE = 'postgresql'<br />
    DATABASE_NAME = 'DjangoPrimer'<br />
    DATABASE_USER = 'bigheadlabs'<br />
    DATABASE_PASSWORD = ''<br />
    DATABASE_HOST = '' # Default: localhost<br />
    DATABASE_PORT = '' # Default port<br />
  </code>
</li>
<li>
  <b>Add our new blog application, the Django authentication application (usually installed by default), and the Django automatic admin site.</b> (The authentication application will automatically allow us to have user authentication, and the admin site will let us control all the applications of our site without having to design these normally tedious pages.)<br />
  <code>INSTALLED_APPS = (<br />
&nbsp;&nbsp;'django.contrib.auth',<br />
&nbsp;&nbsp;'django.contrib.contenttypes',<br />
&nbsp;&nbsp;'django.contrib.sessions',<br />
&nbsp;&nbsp;'django.contrib.sites',<br />
&nbsp;&nbsp;# The following are new.<br />
&nbsp;&nbsp;'django.contrib.admin',<br />
&nbsp;&nbsp;# DjangoPrimer is our project and blog is the application<br />
&nbsp;&nbsp;'DjangoPrimer.blog',<br />
)<br />
  </code>
</li>
<li><b>Add a path to our templates for later.  This has to be an absolute path, so your value will vary.</b><br />
<code>TEMPLATE_DIRS = (<br />
&nbsp;&nbsp;'c:/Projects/DjangoPrimer/templates',<br />
)</code></li>
</ul>
<p>By adding items to the INSTALLED_APPS tuple, we&#8217;re telling Django where the models and views we want to use are located.  We can now create our database, which is <b>DjangoPrimer</b>, the value we specified for DATABASE_NAME in our settings.  (In the interactive shell for your database, you can use &#8220;<code>CREATE DATABASE DjangoPrimer;</code>&#8220;.)  At this point, we can test our configuration by typing <code>python manage.py syncdb</code>.  This will create the database tables for the models for all of our installed applications.  Since we&#8217;re using Django&#8217;s authentication application, we&#8217;ll be able to create our personal superuser account.  If you happened to enter <code>no</code> when it asked you to create the superuser during syncdb, you can create the superuser account by doing <code>python manage.py shell</code> and typing these commands:</p>
<p><code>from django.contrib.auth.create_superuser import createsuperuser<br />
createsuperuser()</code></p>
<p><a name="Models"></a><br />
<h2>Models</h2>
<p>Models are where we begin to define what our data looks like.  If you&#8217;ve had any experience with object-oriented programming languages, then you already know how to model data.  Normally, one would have to create the relational schema and write SQL to define the desired data.  Then, more SQL queries would be needed to grab data from the database.  With Django&#8217;s model API, you only need to create a class to model your data, and Django&#8217;s object-relational mappings will do all the SQL in the background.  (But don&#8217;t worry.  Even if you&#8217;re an SQL expert, you can still write your own, more powerful queries.  Django does not limit you.)</p>
<p>For our purposes, the main component of a blog is a Post, so we&#8217;ll use that to start with our first model.  When you first open models.py in the blog project, you&#8217;ll see one line importing the Django model API.  There isn&#8217;t too much code we need to write here to begin, but let&#8217;s just stop and think about what a simple post usually includes.  Each post has an author, a date/time of post, a title, and the post itself.  The author is a User defined by Django&#8217;s authentication application, the date/time post could be a Python datetime object, and the title and post are just strings.  Let&#8217;s see how we can write a Django model to map to the different data types.<br />
<code><br />
from django.db import models<br />
from django.contrib.auth.models import User<br />
class Post(models.Model):<br />
&nbsp;&nbsp;author = models.ForeignKey(User)<br />
&nbsp;&nbsp;date = models.DateTimeField()<br />
&nbsp;&nbsp;title = models.CharField(maxlength=100)<br />
&nbsp;&nbsp;post = models.TextField()<br />
</code></p>
<p>I&#8217;ve imported User model from the Django authentication application (in the <code>django.contrib.auth</code> package) so that we can reference a User.  When I defined the class, I subclass <code>models.Model</code>, which handles the low-level database methods (such as saving instances of models).  Django&#8217;s model API uses fields to map Python types to database fields (column types).  For instance, Python datetime objects are different from SQL&#8217;s DATATIME data type.  By using the model API&#8217;s fields, the difference between the two are abstracted away.  I will go through each attribute in the model line by line.</p>
<ul>
<li><code>author = models.ForeignKey(User)</code><br />
Each post has an author.  Since we&#8217;re using Django&#8217;s authentication application, we&#8217;ve already got the User model defined for us.  By stating that author is a ForeignKey, we are defining a Many-to-One relationship between the Post and User models.  That is, we are saying that the author attribute references the User model, and a post can have one User as an author, and a User may be the author of any number of Posts.
</li>
<li><code>date = models.DateTimeField()</code><br />
As stated earlier, we want to map Python datetime objects to the SQL DATETIME data type.
</li>
<li><code>title = models.CharField(maxlength=50)</code><br />
The title should be a small string.  Imagine a single-line input text box, as opposed to a multi-line textarea.  We pass the argument <code>maxlength=100</code> to prevent the input from being too large (and thus no longer a title).
</li>
<li><code>post = models.TextField()</code><br />
A post should be a large amount of text.  Even if we didn&#8217;t specify a maxlength for a CharField, there is still a limitation at the database level for CHAR types.  So we use a TextField so our post is not limited in size.
</ul>
<p>If you&#8217;re familiar with SQL, you might be wondering why I haven&#8217;t defined a primary key.  A primary key is simply a unique identifier for each instance of our model (or a row in a table), i.e. to differentiate Post instances from each other.  Django automatically creates a primary key field named <b>id</b> if you do not specify any field in your model as a primary key.  Django uses AutoField, an auto-incrementing integer, as the default primary key.  To specify a different field as a primary key, you can pass in <code>primary_key=True</code> to a field in your model.  (Django currently does not support composite keys, a primary key made from multiple attributes, by specifying multiple primary key attributes)</p>
<p>Now, like we did earlier, we can use <code>python manage.py syncdb</code> to have Django create our new model as a table in the database.  Keep in mind, however, that syncdb will only create tables for new models.  It will not update existing tables if we have changed the model.  In order to update an existing table, you will have to manually alter the table or use <code>python manage.py sqlreset [appname]</code> to drop and re-create the table (which will result in a loss of all data for the models in the application).</p>
<p>Let&#8217;s test out our new model and create our first post.  Since we haven&#8217;t defined any web interfaces (the admin site) to interact with our model yet, we will use the Python console.  <code>python manage.py shell</code> will open the Python console with our project&#8217;s settings already loaded, so we can begin to use it without having to worry about paths or manually loading the settings.</p>
<ul>
<li><b>First we need to import our Post model</b><br />
<code>from DjangoPrimer.blog.models import Post</code></li>
<li><b>And we also need to import the User model so we can point the author to ourselves</b><br />
<code>from django.contrib.auth.models import User</code></li>
<li><b>We need a datetime object to set the date of our post</b><br />
<code>from datetime import datetime</code></li>
<li><b>We can use the Database API to query for the user account we created when we first issued a <code>syncdb</code>.</b><br />
<code>me = User.objects.get(id=1)</code><br />
or<br />
<code>me = User.objects.get(username='Jason')</code></li>
<li><b>We can then just create a new instance of a Post and use the object to create our first post.</b><br />
<code>first_post = Post()</code></li>
<li><b>Now let&#8217;s set the attributes of our first post.</b><br />
<code>first_post.author = me<br />
first_post.date = datetime.now()<br />
first_post.title = 'My first post!'<br />
first_post.post = 'How exciting.  That is all!'</code></li>
<li><b>Since Django&#8217;s database API includes transaction management, the data is not automatically saved in the database until we explicitly tell it to save.</b><br />
<code>first_post.save()</code></li>
</ul>
<p>To see that it actually worked, you can look in your database under the blog_post table to see the data you just saved.  You can also use the database API to retrieve all the Post objects.  <code>Post.objects.all()</code> will return a list of all Post objects, which we should see one.  Since it is a list, you can do something like <code>Post.objects.all()[0].title</code> to see that it is indeed our post.  You might notice if you have more than one post, that the string displayed for each Post in the list is <i>Post: Post object</i>, which isn&#8217;t very informative.  If we wanted to, we could write the __str__() method for our Post class to give our objects a string representation.<br />
<code><br />
def __str__(self):<br />
&nbsp;&nbsp;return self.title<br />
</code></p>
<p>Now, when you do <code>Post.objects.all()</code>, the list should show you the title of each Post object.</p>
<p><a name="AdminSite"></a><br />
<h2>The Admin Site</h2>
<p>The models play an important role in a website, but we still have yet to create any web pages with Django.  Normally after we&#8217;ve finished creating the database schema, we would have to create the tools to maintain the tables.  This usually involves implementing the repetitive CRUD (Create, Read, Update, Delete) operations for all of our database tables.  The admin site that is provided by Django automatically gives you this for free.  We&#8217;ve already installed the admin application earlier, so let&#8217;s see how much work we have to put in to get the admin site up and running.</p>
<p>Open the generated <b>urls.py</b> for the project.  Uncomment the line below &#8220;# Uncomment this for admin:&#8221;.  If you&#8217;ve misplaced it, here it is again:<br />
<code>(r'^admin/', include('django.contrib.admin.urls')),</code></p>
<p>In our blog <b>models.py</b>, we need to create a nested class within our Post class called <b>Admin</b> which will provide metadata to the admin site about our model.  We can provide attributes for the metadata, but for now we can just make an empty class so the admin site will display our model.<br />
<code><br />
class Post:<br />
&nbsp;&nbsp;...<br />
&nbsp;&nbsp;class Admin:<br />
&nbsp;&nbsp;&nbsp;&nbsp;pass<br />
</code></p>
<p>So if you were counting, we wrote two lines of code and uncommented one line of code.  Let&#8217;s see what that got us.  We can now start a webserver with <code>python manage.py runserver</code>.  Once it&#8217;s up and running, point your browser to <a href="http://localhost:8000/admin/">http://localhost:8000/admin/</a> and login.  From here, we can create, read, update, and delete data for all of our installed applications.  We can also see the post we created earlier under Posts.  Amazing.</p>
<p>Now let&#8217;s extend the admin metaclass.  You may have noticed that when you listed the blog posts, it showed a list of the titles, and that was it.  If we hadn&#8217;t written the __str__() method earlier, we would have just seen a list of Post objects.  With the <code>list_display</code> attribute, we can choose which attributes of our model to display.  This will also allow us to sort columns in the table by that attribute.  If we wanted to add a search function, we could add the <code>search_fields</code> attribute with a list of fields we wish to search by.  And as a last example, we could and a column which would filter the results by an object.  For instance, if we had multiple authors and we wanted to be able to filter all posts by a particular author, we could use the <code>list_filter</code> object.  Here&#8217;s how our admin metaclass will look now.<br />
<code><br />
class Admin:<br />
&nbsp;&nbsp;list_display = ('author', 'date', 'title')<br />
&nbsp;&nbsp;search_fields = ('title', 'post')<br />
&nbsp;&nbsp;list_filter = ('author', 'date')<br />
</code></p>
<p><img src='http://www.bigheadlabs.com/wp-content/uploads/2007/03/djangoprimer-admin.jpg' alt='Django Primer - Admin site' /><br />
NOTE: The author filter will not show up unless you have posts by more than one author.</p>
<p><a name="GenericViews"></a><br />
<h2>(Generic) Views and URLs</h2>
<p>With most of the backend work done, we can now begin doing frontend work &#8212; and that&#8217;s what a user&#8217;s going to see.  As I stated in the introduction, the view is the backend where all the logic is written and the template is the frontend that is visible to the user.  If we wanted our front page to show the five latest posts, we would create a view which would grab posts from the Post model and pass it into the template.  The template then takes that data and turns it into a presentable web page.</p>
<p>But, like much of what I&#8217;ve already shown, Django takes away the work of writing your own views for redundant tasks by providing generic views to do these tasks for you.  As of this writing, Django provides generic views for:</p>
<ol>
<li>Rendering a template</li>
<li>Redirecting to another URL</li>
<li>Querying data from a model based on dates</li>
<li>Displaying lists of data from a model</li>
<li>Creating, updating, and deleting objects in the models (the remainder of the CRUD)</li>
</ol>
<p>It&#8217;s worth describing the layout of the <b>urls.py</b> module now.  Earlier, we added the admin site to the urls, but we didn&#8217;t really go over what was going on.  The <code>urlpatterns</code> variable being declared is returned from the <code>patterns</code> function.<br />
<code><br />
urlpatterns = patterns('<i>prefix</i>',<br />
&nbsp;&nbsp;( r'<i>regexp</i>', '<i>view or include</i>', { <i>additional parameters</i> ... } ),<br />
&nbsp; ...<br />
)<br />
</code><br />
The first argument to <code>patterns</code> is a common prefix to prepend all views with.  For instance, all of the generic views reside in the <code>django.views.generic</code> package.  For each view provided, we would have to type out <code>django.views.generic.simple.direct_to_template</code>, <code>django.views.generic.date_based.archive_index</code>, and so on.  Using a prefix of <code>django.views.generic</code> would reduce the name of the views we have to pass to <code>simple.direct_to_template</code> and <code>date_based.archive_index</code>, respectively.</p>
<p>The remaining number of arbitrary arguments are tuples which include a regular expression to match URLs and the view to render for the aforementioned URL.  The tuple takes an optional third item, a dictionary, with key-value pairs for additional parameters.  The view may be an <code>include</code> statement instead, which tells Django to look in the module specified for additional URLs.  Django will also prefix all the URLs in the included module with the URL pattern for the included module.  This can be best explained with an example.  We will create a URL for our blog&#8217;s front page to display the latest posts.</p>
<ul>
<li><b>Our blog will be located at &#8220;/blog/&#8221;, and all URLs defined in our blog application will be prefixed by &#8220;/blog/&#8221;.</b><br />
<code>(r'^blog/', include('DjangoPrimer.blog.urls')),</code></li>
<li><b>We can then create a <code>urls.py</code> in our blog application (package).</b><br />
<code>from django.conf.urls.defaults import *<br />
from DjangoPrimer.blog.models import Post<br />
urlpatterns = patterns('django.views.generic.date_based',<br />
&nbsp;&nbsp;(r'^$', 'archive_index',<br />
&nbsp;&nbsp;&nbsp;&nbsp;{ 'queryset' : Post.objects.all(), 'date_field' : 'date', }<br />
&nbsp;&nbsp;),<br />
)<br />
</code></li>
</ul>
<p>The tuple we created for the URL pattern is of most interest.  The regular expression &#8216;^$&#8217; matches nothing more, so when a user visits  &#8220;/blog/&#8221;, this is the pattern that will be matched.  <code>archive_index</code> is a generic view which will display the latest objects by date.  <code>archive_index</code> also has required parameters, <code>queryset</code> which is the QuerySet for our model and <code>date_field</code> which is the name of the field in our model to use for the date.  (The QuerySet is obtained by using our model&#8217;s Manager, which is named <code>objects</code> by default.  Using the manager, we can query the database for certain data from our model.  In this case, we are getting all objects in the Post model.)</p>
<p><a name="Templates"></a><br />
<h2>Templates</h2>
<p>We finally get to write our first template.  Django provides a template language which allows you to add design logic into your pages.  Create a new directory in the template directory you set in the settings earlier named &#8220;blog&#8221;.  Name the template &#8220;post_archive.html&#8221;.<br />
<code><br />
{% for post in latest %}<br />
&nbsp;&nbsp;&lt;h2&gt;{{ post }}&lt;/h2&gt;<br />
&nbsp;&nbsp;&lt;p&gt;{{ post.post }}&lt;/p&gt;<br />
&nbsp;&nbsp;&lt;b&gt;{{ post.author }}&lt;/b&gt; wrote {{ post.post|wordcount }} words on {{ post.date|date }} at {{ post.date|time }}<br />
{% endfor %}<br />
</code></p>
<p><code>{{ variable }}</code> will evaluate a variable in the context of the template, which is provided by the view.  If it encounters a dot (like above), Django will attempt the following lookups in this order: Dictionary key lookup, attribute lookup, method call, or list-index lookup.  Since post is an object of our Post class, we can use an attribute lookup to get the values of the post.</p>
<p><code>{% tag %}</code> is more complex in that it allows for logic, written in Python, to be executed inside of your template.  We are passed a variable, <code>latest</code>, into the context of our template from the view.  <code>latest</code> is a list of the <code>num_latest</code> (default value of 15 if not specified in the URL pattern) newest objects.  In order to get the individual Post objects from this list in our template, we must iterate it using the <code>{% for %}</code> tag, which mimics Python&#8217;s for-loop.</p>
<p>When using the pipe after a variable (<code>{{ variable|filter }}</code>), the variable is passed into a filter which will do work on the variable and return a new string.  We&#8217;ve used this in the template above to get the number of words in the post, and to format the date and time from the datetime object.</p>
<p><a name="Conclusion"></a><br />
<h2>Conclusion</h2>
<p>What?!  Already?  I hope I&#8217;ve covered enough for you to extend your application or for you to create new applications.  I haven&#8217;t covered creating your own views yet, and I barely touched upon using the database API.  I have plans for articles to discuss these topics in greater detail than I wish to write in this primer.</p>
<p>As an exercise, I recommend extending the blog to support listing posts by year/month (there are more generic views which will allow you to do this easily).  For instance, add a URL &#8220;/blogs/2007/&#8221; to list all months with entries in 2007, and &#8220;/blogs/2007/03/&#8221; to list entries in March 2007.  You can also create a new model for comments and use the generic view for creating objects to add support for comments on your blog.</p>
<p>If you want to get a better understanding of the settings file, the official documentation on <a href="http://www.djangoproject.com/documentation/settings/">Django settings</a> is a comprehensive list of all the options.</p>
<p>Use Django&#8217;s documentation on <a href="http://www.djangoproject.com/documentation/generic_views/">Generic Views</a> to see all the parameters the generic views accept.</p>
<p>There are a ton of built-in template tags and filters that I didn&#8217;t get to show in the simple template example.  The <a href="http://www.djangoproject.com/documentation/templates/">template guide</a> is a must-read for any template author.  If you&#8217;re looking at writing your own templates or filters, <a href="http://www.djangoproject.com/documentation/templates_python/">the template guide for Python programmers</a> is your source.</p>
<p>Best of all, the developers of Django have put a beta version of their book online at <a href="http://www.djangobook.com/">djangobook.com</a>.</p>
<p>Feel free to ask any questions you may have in the comments.  I would also appreciate any other comments you may have, whether it be criticism, pointing out errata, or if there is a specific topic that you would like to be covered in the future.  Thanks for reading.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.disqus.net/2007/03/11/a-django-primer/feed/</wfw:commentRss>
		<slash:comments>64</slash:comments>
		</item>
	</channel>
</rss>
