At the Forge - Django Views and Templates
Things are not that interesting if all we have is a single method and if it always does the same thing. For a blog application, we'll presumably want to be able to read a particular posting, or postings, on a particular day. And although we'll get into the model for our blog application next month, it stands to reason that this means we'll need to be able to request blog postings by an individual ID or by date.
Our current URLConf doesn't handle such situations. Indeed, Django requires that we explicitly indicate each possible URL that a user might request and how that URL should be handled. So although we have taken care of blog/, we need to handle such URLs as:
^blog/ID
Luckily, it should be pretty straightforward for us to set up a regular expression that captures such functionality. If we open urls.py once again, we can add another statement:
(r'^blog/(?P<post_id>\d+)/$', 'mysite.blog.views.view_one_posting')
Here, we see something a bit strange and different, namely the use of capturing parentheses, along with ?P and names inside angle brackets. We tell URLConf that whenever we receive a URL that looks like /blog/NUMBER, with one or more digits, we should invoke view_one_posting. Moreover, because we have captured the digits (\d+, in regular expressions) with the name post_id, view_one_posting will be invoked with an additional parameter of post_id.
In other words, once we've modified urls.py to include the above mapping, we now can go back to views.py and say the following:
def view_one_posting(request, post_id):
return HttpResponse("You asked for post '%s'" % post_id)
Then, we can go to http://69.55.232.87:8000/blog/5, and in our browser, we get the following response:
You asked for post '5'
Notice that in the view_one_posting method, we used %s (for strings) to render post_id, rather than %d (for integers). This is because parameters and URLs are passed as strings, rather than integers or other data types. We could, of course, get around this problem by converting the string to an integer, but for our purposes right now, this is enough.
Perhaps this goes without saying, but each method in our Django application is a Python method whose output just happens to be sent to the user's Web browser. You can use any number of Python libraries that you want, and even access databases, filesystems and remote computers. So long as the output is returned as a legitimate HTTP response, your method will work. The application we are building in these examples represents the tip of the iceberg, as far as implementation complexity is concerned.
If we wanted to, we could create a whole Web site using nothing more than the tools we've already seen. However, it quickly would become difficult, and even tedious, to do so, putting all of our output strings as parameters to HttpResponse. The real solution is to put the HTML in external files, interpolating variable values as necessary.
There are a lot of different templating solutions out there, and each has its advantages and disadvantages. The most common type is that used by ASP, PHP, JSP and ERb—the last of which is part of Ruby on Rails—in which the code is interspersed with the HTML. This type of template can be extremely easy for programmers to work with, but it can cause trouble when nonprogramming designers are involved, or if you just want to have a complete separation between code and design.
Such templates can be used by Django, but they are not the default. Rather, Django uses templates that are similar in many ways to the Smarty system for PHP, which avoids the use of actual code in the template by introducing its own, deliberately limited language. So long as a view can pass values to a template, there's no real need for a full-blown programming language inside of a template. It's probably enough to have if/then statements and some basic loops.
This is what Django's default template system provides. In order to use templates, we first modify the settings.py file that sits in the project's main directory. We want to set the TEMPLATE_DIRS variable, giving it a list of one or more directories in which our templates might be found. For example, we could set it to:
TEMPLATE_DIRS = ( "/opt/atf/mysite/templates" )
With this in place, now we create the appropriate directories:
$ mkdir -p /opt/atf/mysite/templates/blog
And, then we create, in that blog subdirectory, a new HTML file, which we call view_one_posting.html:
<html>
<head>
<title>One post</title>
</head>
<body>
<p>This is the "view_one_posting" template.</p>
</body>
</html>
Now, we modify views.py, such that our view_one_posting method can invoke this template. We add the following import statement at the top of the file:
from django.template import Context, loader
Then, we modify view_one_posting to be:
def view_one_posting(request, post_id):
t = loader.get_template('blog/view_one_posting.html')
c = Context({})
return HttpResponse(t.render(c))
Our template is loaded into the variable t, and the context—that is, the variable values we want to pass to our template—is bound to the variable c. We then tell the template to render itself within the context c. In this particular example, we aren't passing any variables in the context, so it is represented by an empty dictionary.
And, if we reload the URL /blog/5 on our site, we should see the following in the browser window:
This is the "view_one_posting" template.
That's certainly better than what we had before, in that the contents of the template are easier to handle (by programmers and designers alike) than a string inside of a view method. But, how do we pass variables to be interpolated?
The answer is quite simple. In the view method, we can pass any variable we like to the template using the context dictionary, in which the keys are the passed variable names, and the values are the passed variable values. So, we can say:
def view_one_posting(request, post_id):
t = loader.get_template('blog/view_one_posting.html')
c = Context({'post_id': post_id})
return HttpResponse(t.render(c))
If we want to see this value in our template, we can view it in double curly braces:
<html>
<head>
<title>One post</title>
</head>
<body>
<p>This is the "view_one_posting" template.</p>
<p>The post_id is {{post_id}}.</p>
</body>
</html>
And, sure enough, when we render this template, we get:
This is the "view_one_posting" template. The post_id is 5.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- RSS Feeds
- New Products
- Using Salt Stack and Vagrant for Drupal Development
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Home, My Backup Data Center
- Validate an E-Mail Address with PHP, the Right Way
- New Products
- Tech Tip: Really Simple HTTP Server with Python
- Ahh, the Koolaid.
2 hours 46 min ago - git-annex assistant
8 hours 46 min ago - direct cable connection
9 hours 9 min ago - Agreed on AirDroid. With my
9 hours 19 min ago - I just learned this
9 hours 23 min ago - enterprise
9 hours 53 min ago - not living upto the mobile revolution
12 hours 44 min ago - Deceptive Advertising and
13 hours 20 min ago - Let\'s declare that you have
13 hours 21 min ago - Alterations in Contest Due
13 hours 22 min ago
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




Comments
Thanks!
Good article. I am newbie to framework web development. I found django to be very picky. And this article helped me get started.
Suggestion for other newbies: Follow the article strictly for the first time. After you are successful in the first pass, make changes to suit your own needs.
Minor Syntax Point
Great article, I like your approach, I'm a fan of your column and LJ in general.
One thing that you might want to fix is the function definitions for the views. The Python code should be indented properly otherwise it won't run. Maybe my browser or the rendering was off, but you might want to check it, or just mention it.
Thanks for taking a tour of Django and writing about it. I've been using Django for a little while now and enjoy working with it very much.