+ All Categories
Home > Documents > Accelerating Information Technology...

Accelerating Information Technology...

Date post: 18-Jul-2018
Category:
Upload: dinhnhi
View: 225 times
Download: 0 times
Share this document with a friend
88
Accelerating Information Technology Innovation http://aiti.mit.edu Nigeria Summer 2011 Django
Transcript

Accelerating Information Technology

Innovation

http://aiti.mit.edu

Nigeria Summer 2011 Django

Google App Engine

Your Django app

Mobile Web Browser/ Mobile Web App

The Big Picture

Mobile App Development Course Roadmap

Mobile Applications

Back-End

Django

Google App Engine

Google Datastore

SMS/USSD

Front End

Mobile Web

HTML

CSS

Javascript/JQuery

Android Java

Python with SL4A

Core Interface Client

GAE: ���Main Django App

SMS Gateway

Local App

Desktop Web

Mobile Web

GAE: ���JSON API

GAE: ���Website

Development Tools

•  Operating system – Linux (Ubuntu)

•  Integrated Development Environment – Eclipse (Pydev)

•  Version Control – git (GitHub)

– mercurial (Bitbucket or Google project hosting) – subversion (Google project hosting)

Web design

•  Never design websites from scratch •  Two main options:

– Content Management Systems (CMS) A website straight out of the box Can be modified and customised

– Web frameworks Consists of code libraries that provides functionality for

common components in a website, web app, or web service.

Build your own CMS

Why CMS and Web Frameworks

•  Eases coding for –  Working with forms –  Handling HTTP requests –  Templates for common HTML layouts –  URL mapping –  Database communication –  Session management –  Site security

•  Allows you to focus on design and functionality rather than small details.

•  In this class, we’re going to use a Web Framework called Django

Frameworks: Model-View-Controller (MVC)

•  A paradigm for organizing code often seen in web app frameworks

•  Main idea is: –  Separate the storage and manipulation of data (the model)

and the presentation of data (view) –  Use the Controller to communicate between the model

and view •  Advantages

–  Easier to develop and test model and view independently –  Easier for others to understand

•  Exact roles of model, view, and controller depend on who you ask!

Model-View-Controller (MVC) ���(news site example)

Controller

View Model

•  News stories and images in a database

•  User comments

Layout of stories on mobile phone or desktop browser

Send request for a story

Asks the model for the story and its user comments

Serves requested story

Python Web Application Frameworks for Backend

Django

•  Web application framework, written in Python

•  Released 2005 •  Began with World Online,

that needed to rapidly develop applications for news sites.

•  Named after gypsy jazz guitarist Django Reinhardt (1910-53)

•  Follows the Model-View-Controller paradigm

Why Django?

•  Fast and easy development of web applications – Modular and re-useable. Don’t Repeat Yourself

(DRY) principle – Hides database details

•  Active development and wide community support

•  Successful Django sites http://djangosites.org/ •  Supported by Google App Engine

Model-View-Controller (MVC) ���(news site example)

Controller

View Model

•  News stories and images in a database

•  User comments

Layout of stories on mobile phone or desktop browser

Send request for a story

Asks the model for the story and its user comments

Serves requested story

Django Model-Template-View (MTV) ���(news site example)

View

Template Model

•  News stories and images in a database

•  User comments

Layout of stories on mobile phone or desktop browser

Send request for a story

Asks the model for the story and its user comments

Serves requested story

Model Template View

Model View Controller

Django Architecture

MVC ���(Traditional)

MTV ���(Django)

Google App Engine

•  Google’s cloud computing platform to develop and host web applications

•  Distributed data storage service (The Datastore)

•  Free up to 500 MB of storage and 5 million page views

•  Saves the hassle and initial costs of setting up your own server equipment and software

•  Supports Java and Python

Django: Projects and Apps

•  Django works with projects and apps •  Apps are pluggable (any app can be in multiple

projects)

Website (Project)

Responder (App)

Feedback (App)

Parser (App)

Getting Started with django

1.  Setup website 2.  Create the app(s)

–  Set up the models

–  Set up the views –  Create templates if needed –  Modify the urls

3.  Update database 4.  Start the server

1. Setup website

•  django-admin.py startproject musicSite – Creates musicSite in current directory

•  Default file directory

• An empty file that tells Python this directory is a Python package __init__.py

• Command-line utility that lets you interact with this Django project in various ways manage.py

• Settings/configuration for this Django project settings.py

• The URL declarations for this Django project urls.py

2. Create the app

•  cd musicSite •  django-admin.py startapp musicManager

– Create app named musicManager

•  File directory • An empty file that tells Python this directory is a Python package __init__.py

• Contains classes that specify our models models.py

tests.py • Contains logic and functions for views views.py

Django Model-Template-View (MTV) ���(news site example)

View

Template Model

•  News stories and images in a database

•  User comments

Layout of stories on mobile phone or desktop browser

Send request for a story

Asks the model for the story and its user comments

Serves requested story

Models

What they are?

•  Models are schema for your data –  Classes describing data in

your app –  Classes with attributes for

each data field

Why do we use them? •  Avoid direct work with the

database

•  No need to handle database connections, timeouts, etc. Let django do it for you.

Django fields

•  Define the field and django handles the rest: –  In models.py

active = models.BooleanField() –  Django handles the rest:

•  Bit value in sql database •  Represented as a checkbox on a webpage

•  Validation of values

•  Django has already implemented fields •  Can also implement custom fields

Name Displays as

BooleanField Checkbox

CharField(max_length=x) Single-line textbox

DateField Javascript calendar

DateTimeField Javascript calendar, time picker

DecimalField(max_digits, decimal_places) Decimal numbers

EmailField CharField that validates email address

FileField File upload, stores path in database

FloatField Floating point numbers

ImageField *** Don’t use, unsupported Stores images

IntegerField Integer textbox

PositiveIntegerField Integer textbox for positive integers

TextField Multi-line textbox

TimeField Time picker

URLField Textbox for URLs

Django Relationship Fields

•  ForeignKey(foreign class) – Many-to-one

•  ManyToManyField(foreign class) – Uses a temporary table to join tables together

•  OneToOneField(foreign class) – Enforces uniqueness

Field Options •  blank: if True, field is allowed to be blank. default is False.

•  null: if True, empty fields will be stored as NULL in database.

•  choices: list of 2-tuples, will create a select box instead of CharField class Foo(models.Model):

GENDER_CHOICES = ( ('M', 'Male'), ('F', 'Female'), ) gender = models.CharField(max_length=1, choices=GENDER_CHOICES)

•  default: default value for a field

•  primary_key: if True, this field is the primary key for the model

•  unique: if True, this will have to be unique throughout the table

•  verbose_field_name: provides a human readable file name

DateField and DateTimeField options

•  Auto_now – Any time the object is saved, the field will be

updated with the current time.

•  Auto_now_add – The time will always be equal to the creation date

of the object.

Model Methods

•  __unicode__(): – Equivalent of toString – used for auto-

generated admin pages

•  get_absolute_url() – Used for deciding URLs that reference a specific

object

2. Create the app: Edit models.py class Musician(models.Model): first_name = models.CharField(max_length=50) sur_name = models.CharField(max_length=50) instrument = models.CharField(max_length=100) def __unicode__(): return sur_name+”, “+first_name

class Album(models.Model): artist = models.ForeignKey(Musician) name = models.CharField(max_length=100) release_date = models.DateField() num_stars = models.IntegerField() def __unicode__(): return name

Creating Models Manually

>>> from music.models import Musician

>>> m1 = Musician(first_name='Femi', sur_name='Kuti', instrument='saxophone')

>>> m1.save()

>>> m2 = Musician(first_name='Eric', sur_name='Clapton', instrument='guitar')

>>> m2.save()

Not in database yet

Now in database

Getting data from database: ���Managers and QuerySets

•  Manager class –  interface between the database and the app –  Musician.objects returns a Manager object –  Methods include filter(), exclude(), and order_by()

•  QuerySet class –  collection of objects from the database –  Musician.objects.get_query_set.all() or the

shorter Musician.objects.all() returns QuerySet objects

–  We can refine a QuerySet to produce another QuerySet –  Methods include filter(), exclude(), and order_by()

Filter Data

•  exact: gets an exact match –  Musician.objects.filter(instrument__exact=’saxophone’!

–  Musician.objects.filter(instrument='saxophone') #__exact is implied

•  contains: find if a match is contained inside a field –  Musician.objects.filter(instrument__contains=’sax’)

•  icontains: case insensitive contains –  Musician.objects.filter

(last_name__icontains=’kuti')

Ordering

  Musician.objects.order_by('-last_name', ’first_name’)   First orders by last_name in descending order

(hence the negative sign). If there are last_names that are equivalent, then first_name is ordered in ascending order.

Values

•  Musician.objects.values() – Returns a ValueQuerySet, which returns a

list of dictionaries when executed

•  Musician.objects.values(’last_name', ’first_name') – Returns only the fields last_name and first_name in the dictionary

Distinct

•  Musician.objects.distinct() –  If there are any duplicate rows, only one is

returned – This will rarely work like this, because you often

will already have a distinct field, like an id •  Musician.objects.values(‘last_name’, ‘first_name’).distinct() – This will get all unique last_name-first_name combinations

– Notice the chaining here!

Slicing

•  Musician.objects.all()[:5] – Gets the first 5 Musician objects

Get

•  Gets a single row –  raises MultipleObjectsReturned if more than

one object was found. The MultipleObjectsReturned exception is an attribute of the model class.

–  raises a DoesNotExist exception if an object wasn't found for the given parameters. This exception is also an attribute of the model class.

•  Musician.objects.get(id=5) –  Returns a single QuerySet if there is a row that exists,

otherwise an error ensues •  Musician.objects.filter(id=5)[0]

–  Similar, except no exceptions are thrown

When are QuerySets evaluated?

•  Iteration for person in Musician.objects.all(): print person.first_name, person.last_name

•  Boolean if Musician.objects.filter(instrument=“voice"): print "There is at least one Musician that sings"

Creating Models Manually >>> from music.models import Musician

>>> m1 = Musician(first_name='Jimi', last_name='Hendrix', instrument='guitar’)

>>> m1.save()

>>> m2 = Musician(first_name="Eric", last_name=”Clapton”, instrument='guitar’)

>>> m2.save()

>>> Musician_list = Musician.objects.all()

>>> Musician_list [<Musician: Hendrix, Jimi>, <Musician: Clapton, Eric>]

#remember the unicode!!

Filtering >>>Musician.objects.filter(first_name=”Jimi”)‏ [<Musician: Hendrix, Jimi>]

>>>Musician.objects.filter(instrument=”guitar”)‏ [<Musician: Hendrix, Jimi>, <Musician: Clapton,

Eric>]

#returns a QuerySet, not an individual Model Object

>>>Musician.objects.filter(last_name__contains=”Clap”)‏

[<Musician: Clapton, Eric>]

#double underscore!!

Getting >>>Musician.objects.get(first_name=”Jimi”) <Musician: Hendrix, Jimi>

#returns single object

>>>Musician.objects.get(instrument=”violin”) Error! DoesNotExist

>>>Musician.objects.get(instrument=”guitar”) Error! MultipleObjectsReturned

#use try/except when using “get”.

Ordering >>>Musician.objects.order_by(-last_name)‏ [<Musician: Hendrix, Jimi>, <Musician: Clapton, Eric>]

Easier way: add class Meta to Model class

class Musician(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) instrument = models.CharField(max_length=100)

def __unicode__(): return last_name+”, “+first_name

class Meta: ordering = [-last_name]

More Functionality

>>>m1.instrument=”drums” >>>m1.save() #updates ALL rows, could lead to “race” condition

>>>Musicians.objects.filter(id=12).update(instrument=”bass”)‏

#updates only “instrument” row

Chaining

>>>Musicians.objects.filter(instrument="guitar").order_by("-last_name")‏

[<Musician: Hendrix, Jimi>, <Musician: Clapton, Eric>]

Rules of Django Models

1.  If you update a model, UPDATE DATABASE python manage.py syncdb

2.  All classes extend models.Model 3.  Only apps have Models

4.  Django doesn't save objects until you call save() method

Tips for Django Models

1.  Keep code clean 2.  Name your variables well 3.  Don’t think too much about the database

4.  Always create a __unicode__() method

Django Model-Template-View (MTV) ���(news site example)

View

Template Model

•  News stories and images in a database

•  User comments

Layout of stories on mobile phone or desktop browser

Send request for a story

Asks the model for the story and its user comments

Serves requested story

Views

•  Views are the logical interface between data (Models) and presentation (Templates)

•  Defined in views.py inside the appFolder •  EVERY view takes a request object as first parameter •  EVERY view returns an HttpResponse object

from django.http import HttpResponse def hello(request): return HttpResponse("Hello world")

Our views.py from django.template import Context, loader from django.http import HttpResponse from models import Musician

def musicians_list(request): musician_list = Musician.objects.all() t = loader.get_template('musicians/list.html') c = Context({'musician_list': musician_list,}) return HttpResponse(t.render(c))

def musicians_detail(request,id): musician = Musician.objects.get(pk=id) t = loader.get_template('musicians/detail.html') c = Context({'musician': musician,}) return HttpResponse(t.render(c))

Use urls.py to direct HTTP requests to views

# urls.py in musicSite from django.conf.urls.defaults import * from django.contrib import admin urlpatterns = patterns('', url(r'^admin/', include(admin.site.urls)), url(r'^musicians/’, include(musicSite.musicians.urls’))

)

# urls.py in musicians from django.conf.urls.default import * import views urlpatterns = patterns('', url(r'^list/$',views.musicians_list,name='musicians_list'), url(r'^detail/(?P<id>\d+)/

$',views.musicians_detail,name='musicians_detail'), )

Request Life Cycle

1.  User requests to view URL

2.  Django determines the root URLconf by looking at the ROOT_URLCONF setting.

3.  Django looks at all of the URLpatterns in the URLconf for the first one that matches the URL

4.  If it finds a match, it calls the associated view function. –  Repeats Steps 3-4 if redirected to another urls.py

5.  The view function returns an HttpResponse. 6.  Django converts the HttpResponse to the proper HTTP

response, which results in a Web page.

Request Life Cycle

User requests musicians/detail/

2

Django determines root URLConf is urls.py in

musicSite

Django looks up musicians/detail/

2 in urls.py of musicSite

There’s a match, but Django must look up detail/2 in musicians’ urls.py

There’s a match, and Django calls the associated view

function

Django display the HTTPResponse as a web

page

Dynamic Content

# urls.py

from django.conf.urls.defaults import * from mysite.views import hello, current_datetime, hours_ahead

urlpatterns = patterns('', (r'^hello/$', hello), (r'^time/$', current_datetime), )

Dynamic Content

# views.py

from django.http import HttpResponse import datetime

def hello(request): return HttpResponse("Hello world")

def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)

Django Model-Template-View (MTV) ���(news site example)

View

Template Model

•  News stories and images in a database

•  User comments

Layout of stories on mobile phone or desktop browser

Send request for a story

Asks the model for the story and its user comments

Serves requested story

Templates

•  A text-based template for HTML, CSS, XML, JavaScript, etc.

•  Mixture between hard-coded text and abstractions

•  Abstractions – Variables

– Tags

•  Re-useable and extensible

weather.html <html> <head> <title> Weather </title> </head>

<body> <p>Today’s weather in {{ city }} is {{ description }}.</p> <div id=“temperature”> {% for day in thisWeek %} <li> On {{ day.date }}, the temperature will be {{ day.temperature }}. </li> {% endfor %} </div>

<div id="ads"> {% block ads %} Click on these ads! {% endblock %} </div> </body> </html>

Hard-coded Text in weather.html <html>

<head> <title> Weather </title> </head>

<body> <p>Today’s weather in {{ city }} is {{ description }}.</p> <div id=“temperature”> {% for day in thisWeek %} <li> On {{ day.date }}, the temperature will be {{ day.temperature }}. </li> {% endfor %}

</div> <div id="ads"> {% block ads %} Click on these ads! {% endblock %} </div> </body> </html>

Variables

•  {{ variable }} –  If variable doesn’t exist, then output TEMPLATE_STRING_IF_INVALID (default: empty string “”)

•  {{ variable.attribute }} 1.  Dictionary Lookup. variable[“attribute”] 2.  Attribute Lookup. variable.attribute

3.  Method Call. variable.attribute() 4.  List-index Call. variable[attribute]

Filters

•  Modify the output of variables –  {{ variable|filter }}

foo := “Hello World” bar := [‘a’, ‘b’, ‘c’]

{{ foo|lower }} --> hello world {{ bar|length }} --> 3 {{ bar|slice:“:2” }} --> [‘a’, ‘b’] {{ baz|default:“error!” }} --> error!

Tags

•  for loops •  if clauses •  comments

•  blocks •  and many more built-in tags (look them up!)

•  {% tag %} … {% endtag %}

Tags in weather.html <html>

<head> <title> Weather </title> </head>

<body> <p>Today’s weather in {{ city }} is {{ description }}.</p> <div id=“temperature” {% for day in thisWeek %} <li> On {{ day.date }}, the temperature will be {{ day.temperature }}. </li> {% endfor %}

</div> <div id="ads"> {% block ads %} Click on these ads! {% endblock %} </div> </body> </html>

For loops {% for x in y %} … logic … {% endfor %}

fruit_basket := {‘apples’, ‘oranges’, ‘pineapples’}

{% for fruit in fruit_basket %} <li>{{ fruit }}</li>

{% endfor}

<li>apples</li> --> <li>orange</li> <li>pineapples</li>

If clauses

{% if <condition> %} … logic …

{% else %} … logic …

{% endif %}

{% if rain > 1 } Buy an umbrella for {{ price1 }} {% else %} Buy sunglasses for {{ price2 }} {% endif %}

Comments

{% comment %} This comment won’t be displayed! {% endcomment}

•  Ignore everything inside tag – For inline comments, use {# blah blah blah #}

Template Inheritance

•  Define extensible parts of a template with block tags

{% block name %} … {% endblock %} •  Create child templates that can extend blocks •  Load parent template with {% extends “parent_template” %}

Template Inheritance

•  In child template, redefine contents of the parent’s block tag – similar to overriding methods in class inheritance

•  If a block tag is not redefined, then use contents of block tag in parent

•  {{ block.super }} explicitly refers to contents of block tag in parent

weather.html <html>

<head> <title> Weather </title> </head>

<body> <p>Today’s weather in {{ city }} is {{ description }}.</p> <div id=“temperature”> {% for day in thisWeek %} <li> On {{ day.date }}, the temperature will be {{ day.temperature }}.

</li> {% endfor %}

</div> <div id="ads"> {% block ads %} Click on these ads! {% endblock %} </div> </body> </html>

ads.html

{% extends "weather.html" %} {% block ads %} {% if rain > 1 } Buy an umbrella! {% else %} Buy sunglasses! {% endif %} {% endblock %}

Today’s weather in Nairobi is sunny.

•  On Thursday, the temperature will be 20. •  On Friday, the temperature will be 25. •  On Saturday, the temperature will be 22.

Click on these ads!

Buy an umbrella!

city  =  ‘Nairobi‘  descrip1on  =  'sunny‘  thisWeek  =  [dict(date='Thursday',temperature=20),                                              dict(date='Friday',  temperature=25),                                              dict(date='Saturday',  temperature=22)]  rain  =  3  

Context  

Displayed  by  browser  

Templates

•  Mixture of hard-coded text and abstractions •  Abstractions often look like and function like

Python code, but you can’t run arbitrary Python code – Lookup list of built-in filters and tags in Django – Customize your own filters and tags

•  Complex logic with arbitrary Python should be performed by views.py and only the processed variables should be passed to a template

Django Model-Template-View (MTV) ���(news site example)

View

Template Model

•  News stories and images in a database

•  User comments

Layout of stories on mobile phone or desktop browser

Send request for a story

Asks the model for the story and its user comments

Serves requested story

Forms

•  You don’t want to give users access to the admin interface, but you still want them to be able to add/update data

72

Basic HTML form <html>!<head>! <title>Contact us</title>!</head>!<body>! <h1>Contact us</h1>! <form action="/contact/" method="post">! <p>Subject: <input type="text" name="subject"></p>! <p>Your e-mail (optional): <input type="text" name="email"></p>! <p>Message: <textarea name="message" rows="10" cols="50"></textarea></p>! <input type="submit" value="Submit">! </form>!</body>!</html>!

73

Django Form

from django import forms!

class ContactForm(forms.Form):! subject = forms.CharField()! email = forms.EmailField(required=False)! message = forms.CharField()!

74

Form Methods

print ContactForm()!– Prints out HTML code for the form with a table

layout print ContactForm().as_ul()!

– Prints out HTML code for the form as an unordered list

print ContactForm().as_p()!– Prints out HTML code for the form as paragraphs

75

Form Validation

f = ContactForm({'subject': 'Hello', 'email': '[email protected]', 'message': 'Nice site!'}) !

•  When you create an instance of a form using a dictionary as an argument, it will use those values to “fill in” the form on the server

76

Form validation

f.is_bound!– Returns true if the form has been bound to data

f.is_valid() !– Returns true if all values passed to the form are

valid F.cleaned_data!

– Returns a dictionary with all data “cleaned up”

77

Form Error Handling

•  Error handling is done automatically by the form and errors are saved into an instance variable called errors

78

Creating a view def contact(request):! if request.method == 'POST':! form = ContactForm(request.POST)! if form.is_valid():! cd = form.cleaned_data! send_mail(! cd['subject'],! cd['message'],! cd.get('email', '[email protected]'),! ['[email protected]'],! )! return HttpResponseRedirect('/contact/thanks/')! else:! form = ContactForm()! return render_to_response('contact_form.html', {'form': form})!

79

New contact_form.html <html>!<head>! <title>Contact us</title>!</head>!<body>! <h1>Contact us</h1>!

{% if form.errors %}! <p style="color: red;">! Please correct the error{{ form.errors|pluralize }} below.! </p>! {% endif %}!

<form action="" method="post">! <table>! {{ form.as_table }}! </table>! <input type="submit" value="Submit">! </form>!</body>!</html>!

80

Making it better

•  Make message be a Textarea instead of a textbox:

message = forms.CharField(widget=forms.Textarea)!•  Limit subject length: subject = forms.CharField(max_length=100)!•  Adding labels email = forms.EmailField(required=False, label='Your e-mail address')!

81

Making it better

•  Adding initial Values def contact(request):! if request.method == 'POST':! ...! else:! form = ContactForm(! initial={'subject': 'I love your site!'}! )! return render_to_response('contact_form.html', {'form': form})!

82

Making it better

•  Custom validation: –  Inside your form class, you can create custom

methods that will “clean” your variable and throw an exception if it fails

– The Forms class will automatically look for the pattern clean_fieldname, so we can use clean_subject, clean_email, or clean_message!

83

Making it better

def clean_message(self):! message = self.cleaned_data['message']! num_words = len(message.split())! if num_words < 4:! raise forms.ValidationError("Not enough words!")! return message!

84

Do I have to do that every time?

•  No. •  Only if you’re using a form that’s not

controlled by a model.

85

Forms from Models

•  Using our example of a Musician model: from django.forms import ModelForm!class MusicianForm(ModelForm):! class Meta:! model = Musician!

•  That’s it.

86

Forms from Models

•  To create an add form from your class: form = MusicianForm()

•  To create a change form: mus = Musician.objects.get(first_name=“Jimi”) Form = MusicianForm(instance=mus)

87

Forms from Models

•  Saving the input from a form f = MusicianForm(request.POST)!new_musican = f.save()!

•  Restricting fields for the form: class PartialMusicianForm(ModelForm):! class Meta:! model = Musician! fields = (‘sur_name', ‘first_name')!! ! ! exclude = (‘instrument’)!

88


Recommended