Tutorial: - Simon Pami©s

38
Tutorial: repoze.bfg An introduction to Web-Development

Transcript of Tutorial: - Simon Pami©s

Page 1: Tutorial:   - Simon Pami©s

Tutorial: repoze.bfg An introduction to Web-Development

Page 2: Tutorial:   - Simon Pami©s

About and Topics   Simon Pamiés

[email protected]

  Background B. Sc. BioInformatics and Genome Research M.A. IT-Management (Business Analytics)

  Work banality design & communication Senior Application Engineer and Consultant Planning and Development of Web-Applications

  Technologies (excerpt) Zope, Plone, repoze.bfg, J2EE, GWT, jQuery, MongoDB, RabbitMQ

  Basics

  URL Mapping

  Views

  Templates

  Persistence

  Authentication

  Authorization

Page 3: Tutorial:   - Simon Pami©s

About this presentation

  Configuration scheme used here is mostly declarative

  Presentation refers to repoze.bfg version 1.2.x

  Examples imply having a nested package structure with at least   browser/   model/   tests/

  URL mapping is mostly done using dispatching

Page 4: Tutorial:   - Simon Pami©s

repoze.bfg – Introduction

  Framework to ease development of web applications

  Small code and memory footprint

  Uses WSGI protocol

  Very well documented

  Easy to start with

Page 5: Tutorial:   - Simon Pami©s

Goals

  Simplicity (parsimonious feature set)

  Speed (e.g. no regexps on url matching)

  Extensibility

  „Like Zope but less“

  „Like Pylons but more“

Page 6: Tutorial:   - Simon Pami©s

Blather

  repoze.bfg is built upon the WebOb library   ... that provides request and response base classes   ... that handles encoding and decoding of data (e.g. POST)

  repoze.bfg is built to play nicely with WSGI   ... protocol that connects a web server and application together   ... notion of a „pipeline“ where request goes through

  repoze.bfg is also known as BFG (Big Fine Gun, ...)

Page 7: Tutorial:   - Simon Pami©s

It doesn‘t do

  Persistence

  Session

  Indexing

  Restricted code execution

  Authentication

  ...

Page 8: Tutorial:   - Simon Pami©s

repoze.bfg vs.

  Zope 2+3 (ZTK, BlueBream, ...)   Big, Needs some amount of cognitive load to be understood

  Grok   Easy to start with, hard to continue (much magic)

  Django   Full-stacked (makes assumptions about the persistence layer)

  Pylons   Lacks features like object traversal

Page 9: Tutorial:   - Simon Pami©s

URL Mapping

  URLs are entry points to your web app

  Each URL (including parametrized ones) leads to one specific response of your application   e.g. /login, /dashboard, /member/profile, /member/preferences

  An URL is composed of different segments and parameters   e.g. /A/B/C or /A/B/SomeAction?param=value

Key-Question for every web application

How to map URLs to code?

Page 10: Tutorial:   - Simon Pami©s

Routing

  Routing takes the whole URL (including defined parametrized segments) and tries to find a matching rule (the most specific one)

  /logout   /member/12345/profile   /member/12345/profile/messages   /actions/some-ajax-query?param=value

Page 11: Tutorial:   - Simon Pami©s

Routing (Example)

<route path = „/member/:uid/logout“ name = „logout-handler“ view = „.user.logoutHandler“ />

def logoutHandler(context, request): useruid = request.matchdict.get(‚uid‘) return webob.Response(„User has been logged out“)

Page 12: Tutorial:   - Simon Pami©s

Traversal

  Traversal automagically maps each segment to objects

  Walks the object graph

  Context is set according to the last segment matching an object

  Useful in applications where you have dynamic object hierarchies (CMS)

Page 13: Tutorial:   - Simon Pami©s

Traversal (Example)

URL

OBJECT GRAPH

  B is the last object matching the route   Z is the view name   B is passed to the view as context

Page 14: Tutorial:   - Simon Pami©s

Traversal (Example)

<view name = „edit“ context = „.models.folder“ view = „.browser.folder.editHandler“ />

def editHandler(context, request): # context is a folder return webob.Response(„Some HTML to edit a folder“)

Page 15: Tutorial:   - Simon Pami©s

Views

  Methods or classes that act as URL targets

  Work on request object containing all relevant information

  Context provides object that links to model

  View always returns webob.Response

Page 16: Tutorial:   - Simon Pami©s

View (Method based)

def requestHandler(context, request): # do some fancy stuff return webob.Response(„body content here“)

  context is not required but if present holds model related data

  request is an object containing all relevant data

  request.params, request.GET, request.POST

  request[„HTTP_REFERER“]

Page 17: Tutorial:   - Simon Pami©s

View (Class based)

class UserRelatedActionsView(object):

def __init__(self, context, request): self.context = context self.request = request

def __call__(self): return webob.Response()

  Using a class you can group and reuse functionality

  Mainly used for templates to provide tool like interface

  If in doubt use methods

Page 18: Tutorial:   - Simon Pami©s

Templates

  Using Python to build HTML documents sucks

  Use a templating language (e.g. Chameleon ZPT)   Full ZPT implementation   Template compiler   In-place expression evaluation supported

<html> <b tal:condition=„context.hasTitle()“> ${context.Title()} </b>

</html>

Page 19: Tutorial:   - Simon Pami©s

Combining Views and Templates

class LoginView(object):

def isAuthenticated(self): return ‚repoze.who.userid‘ in self.request

def __call__(self): return {‚param‘ : True} # arbitrary parameters here

<b tal:condition=„not view.isAuthenticated() and param“> Please login using the form below

</b>

<route name=„login-form“ view=„.login.LoginView“ renderer=„templates/login_form.pt“ />

Page 20: Tutorial:   - Simon Pami©s

Combining Views and Templates

class LoginView(object):

def __call__(self): from repoze.bfg.chameleon_zpt import render[...] return render_template_to_response( ‚templates/login_form.pt‘, view=self, request=self.request, param=True)

<b tal:condition=„not view.isAuthenticated() and param“> Please login using the form below

</b>

Page 21: Tutorial:   - Simon Pami©s

Renderer

  Built-in renderers available   String   JSON   Chameleon Templates

  Easy to write your own renderer

Page 22: Tutorial:   - Simon Pami©s

Lessons learned?

  repoze.bfg filling the gap between other frameworks

  Notion of URL mapping

  Traversal

  Routing

  Views (Method vs. Class)

  Templates

Page 23: Tutorial:   - Simon Pami©s

What next?

  Persisting data (model) – you‘re free to choose where   ZODB   RDBMS   „No-SQL“ (MongoDB, ...)

  Security   Authenticating users (repoze.who)   ACLs (repoze.bfg, repoze.what)

  Practical part   Installation (buildout, paster), examples

Page 24: Tutorial:   - Simon Pami©s

Persisting data

  Two easy steps   Write your model using plain python objects   Attach a persistent data handler

Your code should not know anything about the storage

  Model   Plain Python object using values from internal state (__dict__)

  Handler   At transaction boundaries (e.g. request) or upon app request

persists data from object to database or the way round

Page 25: Tutorial:   - Simon Pami©s

The Model

From your_db_handler import Persistent

class Person(Persistent):

def __init__(self, name): self.name = name

  The base class takes care of all operations related to the attached storage

  Your class just computes data based on values from known attributes (e.g. name)

Page 26: Tutorial:   - Simon Pami©s

The handler (just to get the idea)

class Persistent(object):

def save(self): if self.isNew(): self.connector.create(self.__dict__) else: self.connector.update(self.__dict__)

def delete(self): self.connector.delete(self.uid)

Page 27: Tutorial:   - Simon Pami©s

Batteries included (ZODB Handler)

  ZODB gives you   full fledged object oriented database   transaction awareness   transparent model handling   scalability

  ZODB can be included with just a few lines of code into your app – and it just works™

  Include ZODB into your model „from persistent import Persistent“

Page 28: Tutorial:   - Simon Pami©s

Security (Authentication)

  Application needs to   authenticate user

  persist authentication

  return state of authentication

  Authenticating: Basic Auth, Form, SSPI

  Persisting: Cookie, Session, URL token

  State: Variable in request

Page 29: Tutorial:   - Simon Pami©s

repoze.who

  Framework to handle authentication   Well thought architecture

  Easily extensible

  Rich set of predefined handlers

  „Who is coming in?“

Page 30: Tutorial:   - Simon Pami©s

repoze.who (cont.)

  Four stages where code can plug in   Classifier (What type of request do we have?)   Challenger (How to get auth data?)   Authenticator (How to check wheter data is valid?)   Persister (How to save valid data?)

  Simple configuration

  Many plugins available Cookie Auth, Basic Auth, Facebook Auth, OAuth

Page 31: Tutorial:   - Simon Pami©s

repoze.who configuration

[general] request classifier and challenge decider

[identifiers] extract data from request

[authenticators] authenticates user based on data from identifiers

[challengers] get user login data (basic auth, form based)

Page 32: Tutorial:   - Simon Pami©s

Security (Authorization)

  Authorization asks „User Bob has permission Edit?“

  User –(1:n)–> Group –(1:m)–> Permissions

  Protecting   Code (e.g. getTitle() method )   Views and URLs (e.g. /person/create-form)

  repoze.bfg has simple authorization handling included

  I recommend against using repoze.what (way to complicated)

Page 33: Tutorial:   - Simon Pami©s

Authorization using repoze.bfg

  Use authentication policy to define groups for users   e.g. repozewho1authenticationpolicy

  Implement or use authorization policy to check for rights   e.g. aclauthorizationpolicy

Page 34: Tutorial:   - Simon Pami©s

Practical Part: What?

  Simple „Hello World“ application   Wiring a view with a template   Handling form submission (POST)

  Another simple application (address book)   Creating a model (person)   User can create persons   Persons are listed and can be deleted

Page 35: Tutorial:   - Simon Pami©s

Practical Part: Installation

  Checking setuptools $ easy_install http://peak.telecommunity.com/dist/ez_setup.py

  Creating a virtualenv environment $ virtualenv –no-site-packages repozebfg

  Installing repoze.bfg $ bin/easy_install repoze.bfg==1.2.1

  Things to understand   Virtualenv   Setuptools

Page 36: Tutorial:   - Simon Pami©s

PP: Setting up a project

  Creating a simple project structure $ bin/paster create -t bfg_starter helloworld

  Things to understand   PasteScript   Python Packages and Eggs

Page 37: Tutorial:   - Simon Pami©s

PP: Starting up the application

  Fire up server $ bin/paster serve –reload helloworld.ini

  Things to understand   WSGI   Python WSGI reference implementation   PasteDeploy framework

Page 38: Tutorial:   - Simon Pami©s

PP: Next steps

  Understanding the structure   helloworld.ini   run.py   configure.zcml   views.py

  Writing some code   Creating a form   Validating form   Saving data