Home Accessibility Courses Twitter The Mouth Facebook Resources Site Map About Us Contact
Python and Tcl - public course schedule [here]
Private courses on your site - see [here]
Please ask about maintenance training for Perl, PHP, Lua, etc
Django - adding your own views, and then templating your views.

Django is a web framework in Python using DRY (Do not repeat yourself) principles. It usually uses data held in a database such as SQLite or MySQL, which is maintained separately from the look and feel of the web site.

This is the second article in a series. For the first article in this series - "Django First Steps" - see [here].

So far (in the first article) we have learned what Django is, and we have installed it with a test server. We have created a project called "oursystems" and within it a project called "nets". Within nets we have created a database table called System into which we "seeded" some test data via the SQLite utility.

We then enabled the admin application that's supplied with the Django distribution, and used it to view the data held in our table (a.k.a. the model) via a browser, and to update the data too, adding, deleting and amending records without the need to know or see the underlying python, SQL or HTML.

We now want to present that data prettily and with good navigability to our web site visitors, who don't care a toad's umbrella about the technology that's behind the website.

Setting up views

Let's plan ahead for a moment - lets work out the types of views that we want, and how we would like their URLs to read. To navigate all of our systems, we'll need some sort of frontpage, and some sort of page to display the details of a particular system select on the front page - so that's:

a) Data Summary / index page
  We'll call that the index page, and give it an index.html URL
b) Individual host pages
  We'll call those single pages, and give it them {sysname}.html URLs

Let's add those to the url.py file, with some other tweaks too - allowing .htm as well as .html extensions, and also setting the absence of a page name to point to the index page - i.e. to make it the home page:
  (r'^hosts/$', 'nets.views.index'),
  (r'^hosts/index\.htm', 'nets.views.index'),

You'll note that we've chosen to put the whole application under what is in effect a virtual directory called /hosts/ as this will allow us flexibility within the domain later on for other demos which can be at a sibling level, and that we're using regular expression match-and-capture to map complete patterns to a single callback method, passing in the pertinent changing bits of the pattern.

Even before we start putting the content of our database into our page, let's check the URL mapping and see how we'll use Python code to fulfill the request - and that's done by providing methods in the views.py file of the application:
  from django.http import HttpResponse
  def index(request):
    return HttpResponse("Index page - list of hosts")
  def single(request,system_id):
    return HttpResponse("About host <b>" + system_id + "</b>")

Now run the server to test those:

  munchkin:oursystems grahamellis$ python manage.py runserver

And browse to the home page, a specific system page, and a page that doesn't map.

Hello Django index view

Hello Django single record view

Hello Django 404

Adding model information to views

To add model data to the views that are generated from Python, you can simply import the classes in the model.py file into the views and make use of the methods provided there and the data behind them. We'll see some issues, and wys to improve this, at the next stage, but let's learn the base mechanism first:

from nets.models import System
  from django.http import HttpResponse
  tail = '<hr /><a href=http://www.wellho.net>Well House Consultants</a>'
  def index(request):
    html = ''
    for h in System.objects.all():
      html += '<br />&bull; <a href=' + h.name + '.html>' + h.name + '</a>'
    return HttpResponse("Index page - Systems registered" + html + tail)
  def single(request,system_id):
    html = 'Unknown'
    for h in System.objects.all():
      if h.name == system_id:
        html = "&bull; at: " + h.ip + "<br />• about: " + h.about
    linkback = "<hr /><a href=index.html>[home]</a>"
    return HttpResponse("About host <b>" + system_id + "</b><br />" + html + linkback + tail)

And we can now browse to those pages, which will display the list of systems with working links from the database, and each of the single pages will work and link back too:

Base demo - index page

Base demo - example (typical) record

Base demo - mapping to non-existant record

Not only do the pages work, but we can add pages for other systems purely by using the admin application that we set up in the first section of this introduction to Django. No need for the person who's maintaining the data to understand Python. Or SQL. Or even HTML. Bingo - we have uncoupled site development from data maintainaince!

BUT (there had to be a "but", I'm afraid!), the HTML is all being generated by our Python code, so we've still got the programmer and the graphic artist intermeshed within the single file. We can't easily change the look of the page to give it an "Easter Bunny" effect in April, nor can we change the data structure easily without effecting the HTML. Furthermore, the look and feel is defined in both the index and the single methods; that's not the DRY philospohy, and it's a potential doubling of work.

Projecting the information through a template

The 'classic' solution that we teach to make people DRY when we find them cutting and pasting gobs of code on a course is to suggest they consider:
a) put the code in a loop
b) put the code in a function
c) put the code in a method
d) ask if someone else has already written a function / method to do it and if they have, use it!

And we're going to apply that classic solution here.

Django already comes with a method that lets you load in a template, and another method which lets you complete that template (actually it comes with a lot more, but let's just take those two steps first.

a) I'm going to take my views and separate out just the varying elements of the pages into separate variables, which I'm going to store in a dictionary that I'll use to create a Context object.

b) I'm going to use a loader to find and load a template - that's a file of HTML with some extra markers in it (call it an HTML++ based metalanguage if you're really feeling geeky) which descibes the look and feel of my pages, and where abouts in them the bits that change should be placed.

c) I'm going to use the render method (that someone else has already written and include as a key part of Django) to fill in the template using te context object, returning to me the HTML, which I'll then pass back to the server as my methods's response.

Just three easy steps ... and indeed you'll learn that there's even a shortcut which lets you combine them later.

Let's see what our views.py now looks like:

from django.template import Context, loader
from nets.models import System
from django.http import HttpResponse
import datetime
year, month, day = datetime.date.today().timetuple()[:3]
def index(request):
  html = ''
  for h in System.objects.all():
    html += '<br />&bull; <a href=' + h.name + '.html>' + h.name + '</a>'

  t = loader.get_template('nets/index.html')
  fill = Context({'listing':html,
    'year' : year,
    'trail': '<a href=http://www.wellho.net/>home</a> -> hostindex',
    'entitled':'The following hosts are currently recorded here'})
  return HttpResponse(t.render(fill))
def single(request,system_id):
  html = 'Unknown'
  for h in System.objects.all():
    if h.name == system_id:
        html = "&bull; at: " + h.ip + "<br />&bull; about: " + h.about
  html += '<br /><br />' + "<a href=index.html>hostindex</a>"
  t = loader.get_template('nets/index.html')
  fill = Context({'listing':html,
    'year' : year,
    'trail': 'home -> <a href=index.html>hostindex</a> -> '+system_id,
    'entitled':'Details about the host called '+system_id})
  return HttpResponse(t.render(fill))

There a still a few patches of HTML in there - but they're all in the dynamic data areas and we'll learn in the next lesson how to move them into the template too. But overall the code is much more segmented.

And we can define a separate template ...

Now I got rather carried away here, and drew up a template that's got style sheets, tables, links, a navigation line showing where you are in the site / application. Also a copyright date ... and all the code for the changing bits is already in the Context objects just above.

The HTML template is quite a lot of lines; the key for you to learn at this stage is that I've added in placeholders for the various context elements in pairs of curly braces - such as
  Copyright © {{year}}, Well House Consultants
for the copyright, so that the year's going to be automatically updated every 1st January without one of us having to get up early in the morning (you may have noticed how quickly we implemented the recent tax rate change - a similar DRY trick!)

One of the security issues that you MUST consider before you put a web application live is the effect of special characters and potential injection attacks, except the Django has done that for you automatically now as you filled in the template. Which is great until you want to pass through some code including characters such as < to the browser without them coming up as &lt; on the display. You can add |safe onto an element in the template to instruct Django's render method NOT to "webify-safe" the content of variables it's filling in - example:
  <div class=trail>{{trail|safe}}</div>

This template should be saved into a separate template directory, and the settings.py file modified in order to have Django look there for it:

Let's start the server again and see how that looks:

Index page from Django

A page produced by Django - nice and consistent series, but otherwise you dont know its Django

Yes - we now have a shared looked and feel between the two different types of page, stored in a single file (nice and DRY), and with the look and feel separated from the data and how it behaves. And there's not a thing in or on the page that gives away the underlying Django and Python techology we've used. As far as our web site visitors - our customers - are concerned, it's just as good as any other website (come to think of it, though, it's probably better. DRY brings you the bonus of consistency of look and feel and user interface, and users love that.)

The complete code for the template is on our web site [here]. Other files (in the state in which they are after this final example in this section) are settings.py and urls.py. Within the nets application, we have also made changes to views.py. Significantly, we have NOT changed models.py in the work done in today's article on Django, as we have been working purely with views and have not had any cause to interfere with the model that we built yesterday.

Review - where are we?

We have a simple table lookup. A templated application. And amendment of table through admin. Really, that's most of what we need for a many a simple application. We could hide the test server behind a proxy (see here), and we should probably improve our error handler for unfound (404) pages - though that could be done by the proxy. In a later article, I'll tell you how to run Django within Apache httpd which you'll probably want to do in the longer term.

And beyond the minimum? What else will we often need / will help us?

• Code in page
• Sharing bits of templates
• Multiple tables that relate
• Updating the tables via your application
• Pulling HTML out of the view file
• Caching, RSS feeds, etc

Those are topics I'll come back to when training; there's an introduction to Django on our learning to program in Python and Python programming courses, and an extra day is available too to cover Django in more depth - I can't tell you everything in that time, but I sure can get you well started.

Articles in this series ..
Step 1
Step 2 -> This is the one you're reading here!
Step 3
(written 2011-01-18, updated 2011-01-20)

Associated topics are indexed as below, or enter http://melksh.am/nnnn for individual articles
Y306 - Python - The Django web framework
  [4095] Django - first steps - Updated - (2013-05-19)
  [4013] Web Frameworks - nested templates - (2013-02-22)
  [3919] What is a web framework? - (2012-11-10)
  [3705] Django Training Courses - UK - (2012-04-23)
  [3698] How to stop forms on other sites submitting to your scripts - (2012-04-15)
  [3640] Sessions (Shopping Carts) in Django - the Python Web Framework - (2012-03-05)
  [3639] Demonstration of a form using Django - (2012-03-04)
  [3634] Defining database relations in your Django model - (2012-03-02)
  [3633] Nesting Templates in Django - (2012-03-02)
  [3624] Why do we need a Model, View, Controller architecture? - (2012-02-25)
  [3140] Django - separating the HTML from the view / model - (2011-01-20)
  [3139] Steering our Python courses towards wxPython, SQLite and Django - (2011-01-19)
  [3136] A framework with python - Django - first steps - (2011-01-17)
  [1745] Moodle, Drupal, Django (and Rails) - (2008-08-08)

Back to
Training Classes - should the training company provide a system for each delegate to use?
Previous and next
Horse's mouth home
Forward to
Steering our Python courses towards wxPython, SQLite and Django
Some other Articles
Private and Public - and things between
Wiltshire Rail services - a golden opportunity
Django - adding your own views, and then templating your views.
Training Classes - should the training company provide a system for each delegate to use?
A time to be brave? We should ask for what is best for our area.
Melksham Weather - Warm and windy becoming colder and calmer
An image from a website that occasionally comes out as hyroglyphics
4759 posts, page by page
Link to page ... 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96 at 50 posts per page

This is a page archived from The Horse's Mouth at http://www.wellho.net/horse/ - the diary and writings of Graham Ellis. Every attempt was made to provide current information at the time the page was written, but things do move forward in our business - new software releases, price changes, new techniques. Please check back via our main site for current courses, prices, versions, etc - any mention of a price in "The Horse's Mouth" cannot be taken as an offer to supply at that price.

Link to Ezine home page (for reading).
Link to Blogging home page (to add comments).

You can Add a comment or ranking to this page

© WELL HOUSE CONSULTANTS LTD., 2019: 404 The Spa • Melksham, Wiltshire • United Kingdom • SN12 6QL
PH: 01225 708225 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho

PAGE: http://www.wellho.net/mouth/3138_Dja ... iews-.html • PAGE BUILT: Sat May 27 16:49:10 2017 • BUILD SYSTEM: WomanWithCat