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
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
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!
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
Top Related