A Brief
Introduction
to Django
overview
What is Django
"Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design."
"The web framework for perfectionists with deadlines"
B/S Model
-
A special form of C/S model.
- Browser send http request.
-
Server returns the requested webpage in html format.
B/S Model
Request
GET /index.html HTTP/1.1
Host: www.example.com
Response
HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
ETag: "3f80f-1b6-3e1cb03b"
Content-Type: text/html; charset=UTF-8
Content-Length: 131
Connection: close
<html>
<head>
<title>An Example Page</title>
</head>
<body>
Hello World, this is a very simple HTML document.
</body>
</html>
Why Web Framework?
If there is no web framework
#!/usr/bin/env python import MySQLdb print "Content-Type: text/html\n" print "<html><head><title>Books</title></head>" print "<body>" print "<h1>Books</h1>" print "<ul>" connection = MySQLdb.connect(user='me', passwd='letmein', db='my_db') cursor = connection.cursor() cursor.execute("SELECT name FROM books ORDER BY pub_date DESC LIMIT 10") for row in cursor.fetchall(): print "<li>%s</li>" % row[0] print "</ul>" print "</body></html>" connection.close()
Why WEB FRAMEWORK
If there is no web framework
- All functionality in one file
- No division of work
- Duplicate code
- Maintaining nightmare
Django Approach
#models.py:
from django.db import models class Book(models.Model): name = models.CharField(max_length=50) pub_date = models.DateField()
#latest_books.html
<html><head><title>Books</title></head> <body> <h1>Books</h1> <ul> {% for book in book_list %} <li>{{ book.name }}</li> {% endfor %} </ul> </body></html>
DJANGO APPROACH
#views.py:
from django.shortcuts import render from models import Book def latest_books(request): book_list = Book.objects.order_by('-pub_date')[:10] return render(request, 'latest_books.html', {'book_list': book_list})
#urls.py
from django.conf.urls.defaults import * import views urlpatterns = patterns('', (r'^latest/$', views.latest_books), )
Django's MVT approach
DJANGO'S MVT APPROACH
- Models: What things are
- Views: How things are processed
- Templates: How things are presented
Project Setup
To demonstrate basics of Django, I will present a tiny example about creating a poll app.
The app can list most recent polls, display poll choices and provide voting functionality.
This example is based on the official Django Tutorial.
Project setup
To start a project called mysite, run:
django-admin.py startproject mysite
The command creates a folder name mysite with following layout:
mysite
├── manage.py
└── mysite
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
PROJECT SETUP
Django provides a tiny web server, Run server by typing
/.manage.py runserver [hostname:port_number]
Project setup
Functionality in Django is organize as applications.
To start an app, run:
./manage.py startapp polls
Another folder is created:
mysite
├── manage.py
├── mysite
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── polls
├── __init__.py
├── models.py
├── tests.py
└── views.py
PROJECT SETUP
To activate poll app, open mysite/settings.py,
edit INSTALLED_APPS:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'polls',
)
Project setup
Modify datebase setup in settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': '', # Or path to database file if using sqlite3.
# The following settings are not used with sqlite3:
'USER': '',
'PASSWORD': '',
'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
'PORT': '', # Set to empty string for default.
}
}
Model
Model
"A model is the single, definitive source of data about your data. It contains the essential fields and behaviors of the data you’re storing.
Django follows the DRY Principle. The goal is to define your data model in one place and automatically derive things from it."
Model
The polls/models.py:
from django.db import models
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
MODEL
We can check model's db representation by typing:
./manage.py sql polls
Output SQL:
BEGIN;
CREATE TABLE "polls_poll" (
"id" integer NOT NULL PRIMARY KEY,
"question" varchar(200) NOT NULL,
"pub_date" datetime NOT NULL
)
;
CREATE TABLE "polls_choice" (
"id" integer NOT NULL PRIMARY KEY,
"poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"),
"choice" varchar(200) NOT NULL,
"votes" integer NOT NULL
)
;
COMMIT;
Run following command to synchronize db.
./manage.py syncdb
The database api
Create:
>>> p = Poll(question="What's up?", pub_date=timezone.now())
>>> p.save()
>>> p
<Poll: What's up?>
>>> p.id
1
>>> p.question
"What's up?"
>>> p.pub_date
datetime.datetime(2013, 11, 09, 18, 17, 38, 553952, tzinfo=)
Create Related Object:
>>> p.choice_set.create(choice_text='Something', votes=0)
>>> c = p.choice_set.create(choice_text='Nothing', votes=0)
>>> c.poll
<Poll: What's up?>
>>> p.choice_set.all()
[<Choice: Something>, <Choice: Nothing>]
THE DATABASE API
Querying:
# get all poll object
>>> Poll.objects.all()
# get poll object which id == 1 >>> Poll.objects.get(pk=1)
# filter poll objects which startswiths 'what' >>> Poll.objects.filter(question__startswith='What')
# filter poll objects which startswiths 'what' and contains 'up'
>>> Poll.objects.filter(question__startswith='What') .filter(question__contains='up')
# get the poll object which is exact 'What's up?' >>> Poll.objects.get(question__iexact="What's up?")
# filter the choice objects whose poll is published in this year and order by id >>> Choice.objects.filter(poll__pub_date__year=current_year) .order_by('id')
Views
"A view is a “type” of Web page in your Django application that generally serves a specific function and has a specific template. "
Hello world
#polls/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the poll index.")
#polls/urls.py
from django.conf.urls import patterns, url
from polls import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index')
)
#mysite/urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^polls/', include('polls.urls')),
)
Hellow world
Runserver and enter the 'polls/' url (default '127.0.0.1/polls/'):
html:
Hello, world. You're at the poll index.
VIew
Now, we want to display the latest 5 polls:
from django.http import HttpResponse
from polls.models import Poll
def index(request):
latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
output = ', '.join([p.question for p in latest_poll_list])
return HttpResponse(output)
Template
Template
The problem of current index view is that the look of webpage is closely related with code in view, which makes modification not flexible at all.
Template system provided by Django can help separate logic of view with presentation of view
Template
#polls/views.py
def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
context = {'latest_poll_list': latest_poll_list}
return render(request, 'polls/index.html', context)
#polls/templates/polls/index.html
{% if latest_poll_list %}
<ul>
{% for poll in latest_poll_list %}
<li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.<\p>
{% endif %}
TEMPLATE
Request
Request
Now, we need to create a detail page to display choices of polls when clicked.
#polls/views.py
def detail(request, poll_id):
poll = get_object_or_404(Poll, pk=poll_id)
return render(request, 'polls/detail.html', {'poll': poll})
#polls/urls.py
urlpatterns = patterns('',
url(r'^$', views.index, name = 'index'),
url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),
)
REQUEST
#polls/templates/polls/detail.html
VOTE
polls/views.py
def vote(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {
'poll':p,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
return render(request, 'polls/detail.html', {
'poll':p,
})
polls.urls.py
url(r'^(?P\d+)/vote/$', views.vote, name='vote'),
vote
Bootstrap
bootstrap
Developed by Twitter
Sleek, intuitive, and powerful mobile first front-end framework for faster and easier web development.
Bootstrap
bootstrap2.3.2/
|-- css
| |-- bootstrap.css
| |-- bootstrap.min.css
| |-- bootstrap-responsive.css
| `-- bootstrap-responsive.min.css
|-- img
| |-- glyphicons-halflings.png
| `-- glyphicons-halflings-white.png
`-- js
|-- bootstrap.js
`-- bootstrap.min.js
Cascading Style Sheets (CSS)
- Style sheet language used for describing the presentation semantics (the look and formatting) of a document written in a markup language.
- Designed primarily to enable the separation of document content from document presentation.
- from Wikipedia
CSS Zen Garden: http://www.csszengarden.com/
CSS basics
- Three kinds of selectors
- Element selector
- ID selector
- Class slector
Element selector
Figure retrieved from http://www.tangowithdjango.com/book/chapters/css_intro.html
ID SELECTOR
Class selector
bootstrap
Bootstrap
To apply bootstrap templates:
- Download bootstrap and jquery, put them into static directory
- Choose the ideal template, copy the source of the template http://getbootstrap.com/2.3.2/examples/starter-template.html
- replace the static links
- Replace body with {% block %} tag
- Modify existing templates
bootstrap
#base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bootstrap, from Twitter</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Le styles -->
<link href="{% static 'css/bootstrap.css' %}" rel="stylesheet">
<link href="{% static 'css/bootstrap-responsive.css' %}" rel="stylesheet">
<style>
body {
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
}
</style>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="brand" href="#">Project name</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<div class="container">
{% block body %}
{% endblock %}
</div> <!-- /container -->
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="{% static 'js/jquery-2.0.3.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
</body>
</html>
bootstrap
#index.html
{% extends 'polls/base.html' %}
{% block body %}
{% if latest_poll_list %}
<ul>
{% for poll in latest_poll_list %}
<li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.<\p>
{% endif %}
{% endblock %}
bootstrap
Django package
django packages
Not only Django Framework, but also various django packages that make Django so popular.
Now, we will apply the package called django-pagination-bootstrap to paginate the index view.
django-bootstrap-pagination
DJANGO PACKAGES
Add 'pagination_bootstrap' to installed app in mysite/settings.py:
INSTALLED_APPS = (
...
'pagination_bootstrap',
)
And configure settings according to documentation.
DJANGO PACKAGES
Modify index.html according to documentation:
{% extends 'polls/base.html' %}
{% load pagination_tags %}
{% block body %}
{% if latest_poll_list %}
{% autopaginate latest_poll_list 2 %}
<ul>
{% for poll in latest_poll_list %}
<li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
{% endfor %}
</ul>
{% paginate_bs2 %}
{% else %}
<p>No polls are available.<\p>
{% endif %}
{% endblock %}
DJANGO PACKAGES
Django
-
Strength
- Full-stack framework
- Rich functionality
- Good documentation
- Weakness
- closed ecosystem
- Weaker functionality than specialized packages
- Inflexible
Bottlt.py
Bottle
"Bottle is a fast, simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module and has no dependencies other than the Python Standard Library." - bottlypy.org
Features:
- Routing
- Templates
- Utilities
- Server support
Hello world
from bottle import route, run, template
@route('/hello/')
def index(name='World'):
return template('Hello {{name}}!', name=name)
run(host='localhost', port=8080)
Bottle
-
Strength
- Lightweight
- Flexible
- Easy to integrate with other packages
- Weakness
- Very basic functionality
- Increasing complexity when grow bigger
More
Some useful Django resources:
- Official Django tutorial https://docs.djangoproject.com/en/1.6/
- Tango with Django http://www.tangowithdjango.com/
- Django book 2.0 http://djangobook.py3k.cn/2.0/