What is Django / What is a Web Framework?
Many web applications have the same elements - a look and feel (the
view, logic that works with the data, usually in a database (the
model), something to handle incoming URLs and run the appropriate piece of logic (a
router) and bespoke glue in the middle that takes the inputs, accesses the model / databases, fills in the view template, and returns the result to the user (the
controller).
These are such repeating elements that a number of
Web Frameworks have been written to provide all the standard stuff for you to tailor. An Object Oriented language (such as PHP, Ruby or Python) allows the web framework provider to provide a structure that's going to support a null (do-nothing) application, in which the web developer can override the skeleton methods to provide functionality. And
components and
helpers can provide extra handlers underneath the web developer's code to provide tasks that will be similar across applications.
Frameworks that I'm currently working with...
• Zend (using PHP as the programming language)
• CodeIgniter (using PHP as the programming language)
• Rails (using Ruby as the programming language)
• Django (using Python as the programming language)
and they're all good. Which to choose? It depends on your metrics, on the programming languages you already know, perhaps on your server and company policy. There are whole article in that discussion. But here's we're going to look at Django.
This article is going to start off from a first Django application - "Hello Django World" - and expand it to cover most of the major elements you'll use in a typical Django application.
Planning
Let's plan our target application first - so that we know where we're headed as we write our Django based application.
Story 1: For this example, I'm going to take a hotel in Melksham, Wiltshire, and write a project that's a resource for guests. Within that project, we'll write an application for day out visits that are available from the hotel. We'll store the information in a database, and we'll have it searchable.
Story 2: We'll go on and add an administration capability to allow for new days out to be added.
Story 3: Then we'll add a user review / rank / comment capability.
Hello Django World
Let's start with
Story 0 - building our project (
guest) and our application (
visit) within it, providing a route from our URL to the application, and initially an index page therein.
1. Check Django Installation:
trainee@brugges:~$ python -c "import django; print(django.get_version())"
1.5.1
trainee@brugges:~$
2. Create the project:
create the project...
cd to where you want to create the project, then:
trainee@brugges:~$ django-admin.py startproject guest
trainee@brugges:~$
and see what you've got:
trainee@brugges:~$ ls -R1 guest
guest:
guest
manage.py
guest/guest:
__init__.py
settings.py
urls.py
wsgi.py
trainee@brugges:~$
3. Start the server and see what you've got:
trainee@brugges:~$ cd guest
trainee@brugges:~/guest$ python manage.py runserver 0.0.0.0:1025
Validating models...
0 errors found
May 19, 2013 - 06:12:20
Django version 1.5.1, using settings 'guest.settings'
Development server is running at http://0.0.0.0:1025/
Quit the server with CONTROL-C.
Browse to your IP address... you should see
and you'll see a log line in the window that you're running the server from:
[19/May/2013 06:12:51] "GET / HTTP/1.1" 200 1956
Once that's tested, ^C (Control - C) in that window will stop the server.
4. Add in your application.
trainee@brugges:~/guest$ python manage.py startapp visit
trainee@brugges:~/guest$
And see what you've done.
trainee@brugges:~/guest$ ls -R1 ../guest
../guest:
guest
manage.py
visit
../guest/guest:
__init__.py
__init__.pyc
settings.py
settings.pyc
urls.py
urls.pyc
wsgi.py
wsgi.pyc
../guest/visit:
__init__.py
models.py
tests.py
views.py
trainee@brugges:~/guest$
In order to access that application, you need to add a route in
urls.py. Within url_patterns:
url(r'^visits/$','visit.views.index'),
url(r'^visits/index\.html?$','visit.views.index'),
And within
settings.py, you need to add the installed application:
INSTALLED_APPS = (
'visit',
And finally, you need to add your
controller (confusingly known as your view) in visit/views.py
# Create your views here.
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello Django")
Run the server again:
trainee@brugges:~/guest$ python manage.py runserver 0.0.0.0:1025
go to visits/ and you should see your "hello" page:
Try index.htm and index.html and you should see the same thing. Try a different page on the same server / in the same application, and you'll see a "not found".
If you've any other errors, various exceptions will be flagged. Check carefully and get them sorted out before you go on to the next stage!
Breaking out your view from the controller class
You've now got your "Hello World" working, but that's just a starter. You really don't want to generate your HTML from within your Python - rather you want a separate look and feel file. Let's write a template, and call it
firsttemplate.htp in a template subdirectory - so we now have:
trainee@brugges:~/guest$ ls -1R
.:
guest
manage.py
visit
./guest:
__init__.py
__init__.pyc
settings.py
settings.pyc
urls.py
urls.pyc
wsgi.py
wsgi.pyc
./visit:
__init__.py
__init__.pyc
models.py
models.pyc
templates
tests.py
views.py
views.pyc
./visit/templates:
firsttemplate.htp
Here's the template I used:
trainee@brugges:~/guest$ cat visit/templates/firsttemplate.htp
<html>
<head>
<title>First Template - Django Demonstration</title>
</head>
<body>
<h1>My Django Application - Mk 1</h1>
The current time is {{ timenowis }}<br /><br />
Copyright and other stuff will be needed too
</body>
</html>
Let's call that template into our view:
from django.http import HttpResponse
from django.template import Context, loader
def index(request):
t = loader.get_template('firsttemplate.htp')
dynamics = Context({ 'timenowis':'lunchtime'})
return HttpResponse(t.render(dynamics))
Here is what I get when I run that:
And you'll notice how I passed data though from the controller to the view via the Context object.
Breaking out the changing section of the page from the generic template
Although an application (or indeed a project) will share a single look and feel, there will usually be a common shell around each page - and using the DRY philosophy of Python and Django, you'll want to move that shared part of the template out into a separate file.
So - how are we going to do that?
1. We'll put the dynamic section of the content in its own template file:
{% extends "visitbase.htp" %}
{% block maincontent %}
<hr />
<i>This is the index page for the </i><b>Visit</b><i> application</i>
<hr />
{% endblock %}
You'll note that we've defined this as a block, and stated that when we render the page it will be include within the visitbase.htp look and feel profile - which is the common surround we'll be sharing all through the application.
Here's that visitbase.htp file:
<html>
<head>
<title>Django Demonstration Template</title>
</head>
<body>
<h1>This headline is shared by all pages within this application</h1>
The current time is {{ timenowis }}<br /><br />
{% block maincontent %} [Default if no matching block] {% endblock %}
<br />Copyright and other stuff will be needed too
</body>
</html>
And note the use of
block again - this time to say where the enclosure goes.
I've also taken the opportunity here to simplify my controller - combining the loader, the complex completion and the HttpResponse constructor into a single helper (shortcut) method that's provided by Django calls
render_to_response.
from django.shortcuts import render_to_response
def index(request):
dynamics = Context({ 'timenowis':'lunchtime'})
return render_to_response('indextemplate.htp',dynamics)
We've still not completed story 0 - we have no data nor model yet, but we do have a
router, a
controller and a
view system running within Django. Probably a good point at which to say we've finished story 0, and take a look at our structure and files.
trainee@brugges:~/guest$ ls -R1 ../guest
../guest:
guest
manage.py
visit
../guest/guest:
__init__.py
__init__.pyc
settings.py
settings.pyc
urls.py
urls.pyc
wsgi.py
wsgi.pyc
../guest/visit:
__init__.py
__init__.pyc
models.py
models.pyc
templates
tests.py
views.py
views.pyc
../guest/visit/templates:
firsttemplate.htp
indextemplate.htp
visitbase.htp
trainee@brugges:~/guest$
This example is for Django version 1.5.1 ... dictory structures were slightly different under previous versions. As I write, 1.5.1 is current, with 1.6 under test and early release; 1.5.1 is best for new production code.
Files used (modified by edit) in the above example:
firsttemplate.htp - first (all in one) template
indextemplate.htp included templare for index page
visitbase.htp - overall application template
urls.py - Router
settings.py - Configuration
views.py - Controller
(written 2013-05-19, updated 2013-05-25)
Associated topics are indexed as below, or enter http://melksh.am/nnnn for individual articles
Y306 - Python - The Django web framework [1745] Moodle, Drupal, Django (and Rails) - (2008-08-08)
[3136] A framework with python - Django - first steps - (2011-01-17)
[3138] Django - adding your own views, and then templating your views. - (2011-01-18)
[3139] Steering our Python courses towards wxPython, SQLite and Django - (2011-01-19)
[3140] Django - separating the HTML from the view / model - (2011-01-20)
[3624] Why do we need a Model, View, Controller architecture? - (2012-02-25)
[3633] Nesting Templates in Django - (2012-03-02)
[3634] Defining database relations in your Django model - (2012-03-02)
[3639] Demonstration of a form using Django - (2012-03-04)
[3640] Sessions (Shopping Carts) in Django - the Python Web Framework - (2012-03-05)
[3698] How to stop forms on other sites submitting to your scripts - (2012-04-15)
[3705] Django Training Courses - UK - (2012-04-23)
[3919] What is a web framework? - (2012-11-10)
[4013] Web Frameworks - nested templates - (2013-02-22)
Some other Articles
Perl Dancer - a Perl Framework - Installation and first testUsing object orientation for non-physical objectsMelksham Chamber of Commerce - Report for AGM, 21st May 2013Perl design patterns exampleDjango - first steps - UpdatedPython Properties - how and whyMore things to make sure that we do NOT do ...Identity in PythonA reminder of why we opened Well House Manor for our customersTest Driven Development in Python - Customer Comes First