Sahana introduction to the code v2

81
Sahana Eden: Emergency Development Environment 2 July 2010, Sahana Camp Fran Boon [email protected]

Transcript of Sahana introduction to the code v2

Page 1: Sahana   introduction to the code v2

Sahana Eden:Emergency

Development Environment2 July 2010, Sahana Camp

Fran Boon

[email protected]

Page 2: Sahana   introduction to the code v2

Stack OverviewServer

Sahana Eden (S3)

Web2Py

Python

HTML

JavaScript

CSS

Client Browser

Eclipse Firebug

Page 3: Sahana   introduction to the code v2

Set yourself uphttp://61.67.7.140/

•Linux:• sudo su -• setup_ubuntu.sh

•Windows:• unzip Sahana-Eden.zip to c:\• Eden-Python-Installer-Dev.exe

• c:\bin\python26

• jre-6u21-windows-i586.exe• putty-0.60-installer.exe

Page 4: Sahana   introduction to the code v2

Windows: Layout• c:\bin\python26• c:\bin\bzr.bat• c:\bin\grep.exe• c:\bin\ssh.exe• c:\bin\eclipse• c:\bin\w2p.cmd• c:\bin\web2py\applications\eden

Add C:\Bin to the system PATH• Control Panel | System | Advanced | Environment Variables• C:\Bin;…

Page 5: Sahana   introduction to the code v2

Configure Eclipse• Perspectives

• Python Interpreter

• New PyDev Project• Web2Py folder

• Debug Configuration• web2py.py• -a password

Page 6: Sahana   introduction to the code v2

Tea

Page 7: Sahana   introduction to the code v2

Morning Session

• Model View Controller– Filesystem Layout

• Web2Py execution model

• S3 REST Controller

• Sahana Modules– Build a New Module

Page 8: Sahana   introduction to the code v2

Model-View-Controller

• web2py/applications/eden/– controllers– models– modules– static– views

Page 9: Sahana   introduction to the code v2

Model-View-Controller• Models

– Define Tables in the Database

• Controllers– Workflow, Logic

• Views– HTML / JS Templates parsed server-side– JS functions then run client-side in browser

Page 10: Sahana   introduction to the code v2

Model-View-Controller

• Static– no server-side processing– Images– CSS– JavaScript

• Modules– Python libraries

Page 11: Sahana   introduction to the code v2

JavaScript

Page 12: Sahana   introduction to the code v2

Models

• All executed every request

• In alphabetical order

• Within web2py environment

Page 13: Sahana   introduction to the code v2

Models

• Define Tables in Database– Live Migrations:

Tables created/altered in database

• Utility functions & variables which are used by multiple controllers

Page 14: Sahana   introduction to the code v2

Core Models

• 000_config.py– deployment settings for easy customisation

• 00_db.py– connect to the database– instantiate classes

• 00_settings.py– read deployment settings & action them

Page 15: Sahana   introduction to the code v2

Core Models (continued)• 00_tables.py

– define some re-usable fields for tables– define admin tables

• 00_utils.py– patch session– utility functions

• 01_crud.py– REST Controller front-end

Page 16: Sahana   introduction to the code v2

Core Models (continued)

• 01_menu.py– build the Menus

• zzz_1st_run.py– Import default data on 1st run

(needs all tables defined 1st)

Page 17: Sahana   introduction to the code v2

Modules• Sahana concept

– Logical grouping of user-facing functionality– Not to be confused with Python modules

• i.e. Not web2py/applications/eden/modules

• Consist of:– Model(s)– Controller– Views

Page 18: Sahana   introduction to the code v2

Sahana Modules• org - Organisation Registry

• pr - Person Registry

• cr - Shelter Registry

• hms - Hospital Management

• rms - Request Management

• vol – Volunteer Management

• msg - Messaging

• gis - Mapping

Page 19: Sahana   introduction to the code v2

Resources• person (pr)• location (gis)• organisation (org)• hospital (hms)• shelter (cr)

Page 20: Sahana   introduction to the code v2

S3 REST Controller• Args:

– /update, /create, /delete

• HTTP verbs:– GET, PUT (POST), DELETE

• Representations:– .html, .json, .xml, .xls, .pdf

Page 21: Sahana   introduction to the code v2

eden module resource

Page 22: Sahana   introduction to the code v2

Emergency• We have to build a module by lunchtime!

Page 23: Sahana   introduction to the code v2

Adding a new module

• Vehicle Tracking System

• Name: vts• Resources:

– vehicle– driver– location

Page 24: Sahana   introduction to the code v2

Model: Define Table

models/vts.py

# Vehicle resource

table = db.define_table("vts_vehicle",

Field("registration"),

Field("make"),

Field("model"),

Field("supplier"),

)

Page 25: Sahana   introduction to the code v2

Controllers

• Entire Controller is executed– Manipulation done outside of functions is visible

to all functions

• Function which has been called is executed

• Functions with no arguments are automatically visible via URLs

Page 26: Sahana   introduction to the code v2

Controller: S3 REST

controllers/vts.py

def vehicle():

return shn_rest_controller("vts", "vehicle")

Page 27: Sahana   introduction to the code v2

View

None needed at 1st – can RAD without them

& then polish later

Try:

http://127.0.0.1:8000/eden/vts/vehicle

1.Create a vehicle.

2.View in different formats:– .json, .xml, .xls, .pdf

Page 28: Sahana   introduction to the code v2

Morning Session

• Model View Controller– Filesystem Layout

• Web2Py execution model

• S3 REST Controller

• Sahana Modules– Build a New Module

Page 29: Sahana   introduction to the code v2

Lunch

Page 30: Sahana   introduction to the code v2

Afternoon Session

• Web2Py Shell• Views• Extend our New Module• Internationalisation• Menus• Joined Resources• DAL: Database Abstraction Layer• Mapping

Page 31: Sahana   introduction to the code v2

Exploring: Web2Py shell• Python is great for interactive exploring!

– Web2Py allows this too

w2p

python web2py.py –S eden –M

• Explore objects with tabdb.

gis.

Page 32: Sahana   introduction to the code v2

Views: Web2Py• Defaults to views/controller/function.html

• Python code inside {{ }} is parsed server-side

• Views can extend & include other views

• Extend ‘layout’ for overall look/feel{{extend "layout.html"}}

Page 33: Sahana   introduction to the code v2

Views: S3 REST

• REST has defaults– create.html– display.html– list.html– List_create.html– update.html

Page 34: Sahana   introduction to the code v2

Views: Custom

• They can also be customised: views/vts/vehicle_list_create.html

{{extend "layout.html"}}

{{rheader="Register a new vehicle in the system:"}}

{{include "_list_create.html"}}

Page 35: Sahana   introduction to the code v2

Internationalisation

{{rheader=T("Register a new vehicle in the system:")}}

http://127.0.0.1:8000/admin/default/design/eden#languages

Update all languages

Page 36: Sahana   introduction to the code v2

InternationalisationTry these in the shell: w2p

•print T("My Text")

•print T("<P>My HTML</P>")

•print "<P>" + T("My HTML") + "</P>"

•print "<P>" + str(T("My HTML")) + "</P>"

•print "<P>" + Tstr("My HTML") + "</P>“

Page 37: Sahana   introduction to the code v2

ViewsVariables only visible to views if:

•explicitly passed in return dict()

•stored in global variables:•request, response, session

http://127.0.0.1:8000/eden/default/about

Page 38: Sahana   introduction to the code v2

Model: SQL constraints

models/vts.py

table = db.define_table("vts_vehicle",

Field("registration", unique=True),

Field("make"),

Field("model"),

Field("supplier"),

)

Page 39: Sahana   introduction to the code v2

Model: Validators

models/vts.py

table = db.define_table("vts_vehicle",

Field("registration", unique=True),

Field("make"),

Field("model"),

Field("supplier"),

)

table.registration.requires = NOT NEEDED!

IS_NOT_IN_DB(db, table.registration)

Page 40: Sahana   introduction to the code v2

Model: Field Types

models/vts.py

table = db.define_table("vts_vehicle",

Field("registration", unique=True),

Field("make"),

Field("model"),

Field("purchase_date", "date"),

Field("supplier"),

)

Page 41: Sahana   introduction to the code v2

Model: Default Values

models/vts.py

table = db.define_table("vts_vehicle",

Field("registration", unique=True),

Field("make"),

Field("model"),

Field("purchase_date", "date", default=request.utcnow),

Field("supplier"),

)

Page 42: Sahana   introduction to the code v2

Controller: Labels controllers/vts.py

def vehicle():

db.vts_vehicle.registration.label = "License Plate"

return shn_rest_controller("vts", "vehicle")

Page 43: Sahana   introduction to the code v2

Controller: Labels controllers/vts.py

def vehicle():

db.vts_vehicle.registration.label = T("License Plate")

return shn_rest_controller("vts", "vehicle")

Page 44: Sahana   introduction to the code v2

Controller: Comment controllers/vts.py

def vehicle():

db.vts_vehicle.registration.label = T("License Plate")

db.vts_vehicle.registration.comment = \

SPAN("*", _class="req")

return shn_rest_controller("vts", "vehicle")

Page 45: Sahana   introduction to the code v2

Controller: CRUD Strings controllers/vts.pydef vehicle():

s3.crud_strings["vts_vehicle"] = Storage(

title_create = T("Add Vehicle"),

title_display = T("Vehicle Details"),

title_list = T("List Vehicles"),

title_update = T("Edit Vehicle"),

label_create_button = T("Add Vehicle"),

msg_record_created = T("Vehicle added"),

)

Page 46: Sahana   introduction to the code v2

Controller: Action buttons

controllers/vts.pydef vehicle():

def veh_postp(jr, output): shn_action_buttons(jr)

return output

response.s3.postp = veh_postp

output = shn_rest_controller("vts", "vehicle")

return output

Page 47: Sahana   introduction to the code v2

How do we Navigate?• Modules menu

• Modules list on frontpage

• Menu within Module

Page 48: Sahana   introduction to the code v2

URL(r=request, a=application, c=controller, f=function, args=[], vars={})

Page 49: Sahana   introduction to the code v2

Enable Module models/000_config.py

deployment_settings.modules = Storage(

vts = Storage(

name_nice = "Vehicle Tracking System", description = "Track vehicles",

module_type = 10

),

)

Page 50: Sahana   introduction to the code v2

Index page controllers/vts.py

module = request.controller

def index():

"Custom View"

module_name = \ deployment_settings.modules[module].name_nice

return dict(module_name=module_name)

Page 51: Sahana   introduction to the code v2

View

views/vts/index.html

{{extend "layout.html"}}

{{=H2(T(module_name))}}

<p>This module allows users to track their vehicles</p>

{{=LI(A("List Vehicles", _href=URL(r=request, f="vehicle")))}}

Page 52: Sahana   introduction to the code v2

Controller: Menu controllers/vts.py

response.menu_options = [

[T("Vehicles"), False, URL(r=request, f="vehicle"),[[T("List"), False, URL(r=request, f="vehicle")],

[T("Add"), False, URL(r=request, f="vehicle", args="create")] ]]]

Page 53: Sahana   introduction to the code v2

Tea

Page 54: Sahana   introduction to the code v2

Joined Resources

• So far:– Resource = Single Table

• Reality:– Resource spread out over multiple Tables

Page 55: Sahana   introduction to the code v2

Joined Resources: Model

• Link Vehicle to Location– vts_presence

Page 56: Sahana   introduction to the code v2

Joined Resources: Model

models/vts.pymodule = "vts"

resource = "presence"

tablename = "%s_%s" % (module, resource)

table = db.define_table(tablename,

Field("vehicle_id"),

Field("location_id"),

)

Page 57: Sahana   introduction to the code v2

Joined Resources: Model

models/vts.py

table = db.define_table(tablename,

Field("vehicle_id", db.vts_vehicle),

Field("location_id", db.gis_location),

)

Page 58: Sahana   introduction to the code v2

Joined Resources: Model

models/vts.py

table = db.define_table(tablename,

Field("vehicle_id", db.vts_vehicle),

location_id,

)

Page 59: Sahana   introduction to the code v2

Joined Resources: Controller controllers/vts.py

def presence():

resource = request.function

return shn_rest_controller(module, resource)

http://127.0.0.1:8000/eden/vts/presence

Page 60: Sahana   introduction to the code v2

Joined Resources: Model

models/vts.py

table = db.define_table(tablename,

Field("vehicle_id", db.vts_vehicle),

location_id,

)

table.vehicle_id.requires = IS_ONE_OF(db,

"vts_vehicle.id",

"vts_vehicle.registration")

Page 61: Sahana   introduction to the code v2

Joined Resources: Model

models/vts.py

table = db.define_table(tablename,

Field("vehicle_id", db.vts_vehicle),

location_id,

Field("time", "datetime"),

)

table.vehicle_id.requires = IS_ONE_OF(db, "vts_vehicle.id", "vts_vehicle.registration")

table.time.requires = IS_DATETIME()

Page 62: Sahana   introduction to the code v2

DAL:Database Abstraction Layer• SQLite

• out of the box

• MySQL• well-tested with Eden

• PostgreSQL• what we want to use for Spatial support

• Oracle, DB2, MS SQL, Firebird, GAE

Page 63: Sahana   introduction to the code v2

DALTry these in the shell: w2p

db.define_table("person", Field("name"))

id = db.person.insert(name="max")query = (db.person.id == id)

db(query).count()

db(query).update(name="Max")

rows = db(query).select(orderby=db.person.name)for row in rows:

print row.name

db(query).delete()

Page 64: Sahana   introduction to the code v2

DAL

• For shell scripts (e.g. Cron tasks):

db.commit()

• Beware locking (SQLite)

Page 65: Sahana   introduction to the code v2

JR: Represent models/vts.py

table.vehicle_id.represent = lambda id: \db(db.vts_vehicle.id == id).\ select().first().registration

table.vehicle_id.represent = lambda id: db(db.vts_vehicle.id == id).\ select(limitby=(0,1)).first().registration

table.vehicle_id.represent = lambda id: db(db.vts_vehicle.id == id).\ select(db.vts_vehicle.registration, limitby=(0,1)).first().registration

Page 66: Sahana   introduction to the code v2

JR: Components models/vts.py

# Presence as component of vehicle

s3xrc.model.add_component(module,

resource,

multiple=True,

joinby=dict(vts_vehicle="vehicle_id"),

deletable=True,

editable=True)

http://127.0.0.1:8000/eden/vts/vehicle/1/presence

Page 67: Sahana   introduction to the code v2

Components: RHeader controllers/vts.pydef shn_vts_rheader(jr, tabs=[]):

if jr.representation == "html":

rheader_tabs = shn_rheader_tabs(jr, tabs)

vehicle = jr.record

rheader = DIV(TABLE(

TR(TH(T("Vehicle: ")), vehicle.registration,

TH(T("Make: ")), vehicle.make),

TR(TH(T("Purchase Date: ")),

vehicle.purchase_date,

TH(T("Model: ")), vehicle.model)),

rheader_tabs)

return rheader

return None

Page 68: Sahana   introduction to the code v2

Components: Rheader Tabs

controllers/vts.pydef vehicle():

output = shn_rest_controller(module, "vehicle",

rheader=lambda jr: shn_vts_rheader(jr,

tabs = [(T("Basic Details"), None),

(T("Presence"), "presence")

]),

sticky=True)

return output

http://127.0.0.1:8000/eden/vts/vehicle/1/presence

Page 69: Sahana   introduction to the code v2

Show me the Map!

Page 70: Sahana   introduction to the code v2

Map

Different Layers:

•Base

•Overlay– Internal– External (Earthquakes)

Page 71: Sahana   introduction to the code v2

Display on Map

• Map displays Feature Groups

• Feature Groups contain Feature Classes

• Locations have Feature Classes

• “Vehicles” are set up ready to go

Page 72: Sahana   introduction to the code v2

Simplify data entry:GIS Controller

controllers/gis.py

def location()…

if "vts_presence" in caller:

fc = db(db.gis_feature_class.name == "Vehicle").\ select(db.gis_feature_class.id, limitby=(0, 1)).first()

Page 73: Sahana   introduction to the code v2

Simplify data entry:GIS View

views/gis/location_popup.html…

{{elif "vts_presence" in request.vars.caller:}}

// If coming from the VTS then populate defaults for the // fields & Hide unnecessary rows

var location_name = self.parent.\ $('#vts_presence_vehicle_id__row > td.w2p_fw').html();

if (location_name) { $("#gis_location_name").val(location_name); //$("#gis_location_name__row").hide();

}

Page 74: Sahana   introduction to the code v2

HTML5 Geolocation

views/gis/location_popup.html

{{elif "vts_presence" in request.vars.caller:}}

if (navigator.geolocation){

navigator.geolocation.getCurrentPosition(getCurrentPosition);

}

Page 75: Sahana   introduction to the code v2

Documentation

• Examples from other modules

• Developer Guidelines on Wiki:http://eden.sahanafoundation.org/wiki/DeveloperGuidelines

• But the best…?

Page 76: Sahana   introduction to the code v2

Use the Source, Luke!Many resources and tricks on the Internet find you will, but the ultimate answers only in the source lie

Page 77: Sahana   introduction to the code v2

S3 is built on Web2Py

REST

CRUD

SQLFORM

FORM

Page 78: Sahana   introduction to the code v2

Form submission

• Use Firebug’s Net Panel to look at a form submission.

• Each field has an entry in form.vars

• Can add additional vars to the form in a custom View

• Can process these within our Controller– onvalidation: Before DB I/O– onaccept: After DB I/O

Page 79: Sahana   introduction to the code v2

Web2Py CRUD

web2py/gluon/tools.pyself.settings.create_onvalidation = None self.settings.update_onvalidation = None self.settings.delete_onvalidation = None self.settings.create_onaccept = None self.settings.update_onaccept = None self.settings.update_ondelete = None self.settings.delete_onaccept = None

•onvalidation: Before DB I/O

•onaccept: After DB I/O

Page 80: Sahana   introduction to the code v2

Afternoon Session

• Web2Py Shell• Views• Extend our New Module• Internationalisation• Menus• Joined Resources• DAL: Database Abstraction Layer• Mapping

Page 81: Sahana   introduction to the code v2

End