tutorial: - simon pami©s
TRANSCRIPT
![Page 1: Tutorial: - Simon Pami©s](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/1.jpg)
Tutorial: repoze.bfg An introduction to Web-Development
![Page 2: Tutorial: - Simon Pami©s](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/2.jpg)
About and Topics Simon Pamiés
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/3.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/4.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/5.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/6.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/7.jpg)
It doesn‘t do
Persistence
Session
Indexing
Restricted code execution
Authentication
...
![Page 8: Tutorial: - Simon Pami©s](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/8.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/9.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/10.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/11.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/12.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/13.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/14.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/15.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/16.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/17.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/18.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/19.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/20.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/21.jpg)
Renderer
Built-in renderers available String JSON Chameleon Templates
Easy to write your own renderer
![Page 22: Tutorial: - Simon Pami©s](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/22.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/23.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/24.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/25.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/26.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/27.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/28.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/29.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/30.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/31.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/32.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/33.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/34.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/35.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/36.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/37.jpg)
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](https://reader031.vdocuments.site/reader031/viewer/2022021307/6207502249d709492c302df3/html5/thumbnails/38.jpg)
PP: Next steps
Understanding the structure helloworld.ini run.py configure.zcml views.py
Writing some code Creating a form Validating form Saving data