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"

from  https://www.djangoproject.com/

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."

-Django Project

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
<h1>{{ poll.question }}</h1> {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} <form action="{% url 'vote' poll.id %}" method="post"> {% csrf_token %} {% for choice in poll.choice_set.all %} <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /> <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}--{{ choice.votes }} Votes</label><br/> {% endfor %} <input type="submit" value="Vote" /> </form>

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.

http://getbootstrap.com/2.3.2/index.html


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

Figure  retrieved  from http://www.tangowithdjango.com/book/chapters/css_intro.html

Class selector


Figure  retrieved  from http://www.tangowithdjango.com/book/chapters/css_intro.html

bootstrap


http://getbootstrap.com/2.3.2/getting-started.html

Bootstrap

To apply bootstrap 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.
See https://www.djangopackages.com

Now, we will apply the package called django-pagination-bootstrap to paginate the index view.

django-bootstrap-pagination
https://github.com/staticdev/django-pagination-bootstrap

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

http://bottlepy.org/

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:


Thanks!