• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
 

Pyramid Lighter/Faster/Better web apps

on

  • 8,595 views

Gentle introduction to Pyramid. Where it comes from, how simple it, how fast, how flexible and why the future will be pyramid shaped.

Gentle introduction to Pyramid. Where it comes from, how simple it, how fast, how flexible and why the future will be pyramid shaped.

Made for pyconau 2011

Statistics

Views

Total Views
8,595
Views on SlideShare
8,518
Embed Views
77

Actions

Likes
6
Downloads
44
Comments
0

7 Embeds 77

http://lanyrd.com 66
http://paper.li 4
http://twitter.com 2
http://krutubtim.wordpress.com 2
http://a0.twimg.com 1
http://www.twylah.com 1
http://www.docseek.net 1
More...

Accessibility

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

Pyramid Lighter/Faster/Better web apps Pyramid Lighter/Faster/Better web apps Presentation Transcript

  • Lighter/faster/better web apps Dylan Jay CTO PretaWeb.com SyPy.org twitter: djay75
  • From the mind of Chris McDonough As seen in bearded of PyCon 2009 http://www.flickr.com/photos/termie/3392894269/
  • Pyramid Family Tree Zope formally Principia (1996-) Zope2 (1998-) BlueBream formally Zope3 (2004-) ZTK (2009-) Repoze.bfg (2008 – 2010) Pylons (2005-2010) Pylons Project (2010-) Pyramid formally repoze.bfg ( Dec 2010 -) TurboGears (2005-) RoR (2004-) Django (2005-)
  • Who uses it
    • It's still new
    • Karl Project
    • Aeterna Water – paperless sales system
      • “How to build complex web applications having fun”
      • http://slidesha.re/mH9Lxa
      • 1000 employees
      • No ORM = easy integrate with Plone
      • Less Magic. More simple
  •  
  • From the minds on PretaWeb... PloneFactory Web installer for the worlds favourite Python CMS Coming 2011...
  • Differences...
    • Non opinionated framework
    • Component Architecture
    • Packages (eggs)
    • Simpler and faster
    Pyramid Django Plone Not Opinionated Opinionated Structured (CMS) Very Simple Simple Complex No DB ORM Content Types Little Reuse Some Reuse Easy Reuse
  • Performance http://blog.curiasolutions.com/the-great-web-framework-shootout/
  • Performance http://plope.com/pyroptimization
  • Install $ virtualenv -- no-site-packages -- distribute newproject $ cd newproject $ bin/pip install pyramid
  • Hello World from paste.httpserver import serve from pyramid.configuration import Configurator from pyramid.response import Response def hello_world(context, request): return Response('Hello world!') if __name__ == '__main__': config = Configurator() config.begin() config.add_view(hello_world) config.end() app = config.make_wsgi_app() serve(app, host='0.0.0.0')
    • config.add_route('myroute', '/prefix/{one}/{two}') config.add_view(hello_world, route_name='myroute') foo/{baz}/{bar}*fizzle foo/{baz}/{bar}{fizzle:.*}
    • Also custom predicates
    Routes (URL Dispatch)
  • View Callables from pyramid.response import Response def hello_world(request): return Response('Hello world!') from pyramid.httpexceptions import HTTPFound class MyView(object): def __init__(self, request): self.request = request def __call__(self): raise HTTPFound(location='http://example.com')
  • Request / prefix/foo/bar?pref=red&pref=blue; def hello_world(request): assert 'blue' == request.params['pref'] assert ['red,'blue] == request.params.getall('pref') assert ['foo','bar'] == request.matchdict.values() return Response('Hello world!')
  • Renderers from pyramid.view import view_config @view_config(renderer='json') def hello_world(request): return {'content':'Hello!'} @view_config(renderer='string') def hello_world(request): return {'content':'Hello!'} @ view_config(renderer='mypackage:templates/foo.mak') Add your own - config.add_renderer('.jinja2', 'mypackage.MyJinja2Renderer')
  • Templates from pyramid.renderers import render_to_response def sample_view(request): return render_to_response('templates/foo.pt', {' foo':1, 'bar':2}, request=request)
  • Templates from pyramid.renderers import render_to_response def sample_view(request): return render_to_response('templates/foo.pt', {' foo':1, 'bar':2}, request=request)
  • BYO Templating from mako.template import Template from pyramid.response import Response def make_view(request): template = Template(filename='/templates/template.mak') result = template.render(name=request.params['name']) response = Response(result) return response
  • Chameleon ZPT Templates
    • Compiled to python – really fast
    • XHTML complaint
    • .pt files
    <! DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot; http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;> < html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xmlns:tal=&quot;http://xml.zope.org/namespaces/tal&quot;> < head> < meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=utf-8&quot; /> < title>${project} Application</title> </ head> < body> < h1 class=&quot;title&quot;>Welcome to <code>${project}</code>, an application generated by the <a Href=”http://...&quot; tal:attributes=”href mylink” > pyramid</a> web application framework.</h1> < ul > <li tal:repeat=”row rows”>${row}</li></ul> </ body> </ html>
  • Static Assets config.add_static_view(name='static', path='/var/www/static') / static/main.css -> /var/www/static/main.css config.add_static_view(name='static', path='some_package:a/b/c/static') / static/foo.jpg -> ./src/some_package/a/b/c/static/foo.jpg
  • Traversal
  • Traversal (Resource Location) Pattern allowing transitive and indirect view loockup Simplifies view code for complex apps Great for content centric URLS config.add_view(photo_edit, context=Photo, name='edit') Class User(dict): pass Class Folder(dict): pass Class Photo(dict): pass def photo_edit(request): Return Response('editing %s', request.context.Ttile)
  • Inside Traversal / joeschmoe/photos/photo1/edit psuedo code: context = get_root()['joeschmoe']['photos']['photo1'] view_callable = get_view(context,'edit') request.context = context view_callable(request)
  • View Predicates
    • name
    • context (class or interface)
    • route_name
    • request_type (interface)
    • request_method (e.g POST)
    • header
    • request_param (key in request.params)
    • containment (class or interface)
    • xhr
    • accept (mimetypes)
    • path_info (regex)
    • custom_predicates
  • Security - Protecting Authentication Policy – Extract principals from request Authorization Policy – Access based on Context, Principals and View's permissions config.add_view(myview, name='add_entry.html', context='mypackage.resources.Blog', permission='add')
  • Security Configuration def auth(userid, request): return ['user:bob','group:editors'] if userid == 'bob' else None from pyramid.config import Configurator from pyramid.authentication import AuthTktAuthenticationPolicy from pyramid.authorization import ACLAuthorizationPolicy authentication_policy = AuthTktAuthenticationPolicy('seekrit', callback=auth) authorization_policy = ACLAuthorizationPolicy() config = Configurator(authentication_policy=authentication_policy, authorization_policy=authorization_policy)
  • Security - Context from pyramid.security import Everyone from pyramid.security import Allow class Blog(object): pass blog = Blog() blog.__acl__ = [ (Allow, Everyone, 'view'), (Allow, 'group:editors', 'add'), (Allow, 'group:editors', 'edit'), ]
  • Scaffolding $ bin/paster create -t pyramid_starter MyProject $ cd myproj $ ../ bin/python setup.py develop $ ../ bin/paster serve development.ini Starting server in PID 16601. serving on 0.0.0.0:6543 view at http://127.0.0.1:6543 MyProject/ |-- CHANGES.txt |-- development.ini |-- MANIFEST.in |-- myproject | |-- __init__.py | |-- resources.py | |-- static | | |-- favicon.ico | | |-- logo.png | | `-- pylons.css | |-- templates | | `-- mytemplate.pt | |-- tests.py | `-- views.py |-- production.ini |-- README.txt |-- setup.cfg `-- setup.py $ bin/paster create -t pyramid_zodb $ bin/paster create -t pyramid_routesalchemy $ bin/paster create -t pyramid_alchemy
  • Customising
    • Designed Extensible
    • Not “apps” like django
    • Plugpoints
      • Views
      • Routes
      • Assets
  • Customizing Example def configure_views(config): config.add_view('orig_app.views.theview', name='theview') from pyramid.config import Configurator from orig_app import configure_views if __name == '__main__': config = Configurator() config.include(configure_views) config.add_view('override_app.views.theview', name='theview')
  • pyramid_socketio config.add_route('socket_io', 'socket.io/*remaining') config.add_view(socketio_service, route_name='socket_io') from pyramid.response import Response from pyramid_socketio.io import SocketIOContext, socketio_manage class ConnectIOContext(SocketIOContext): # self.io is the Socket.IO socket # self.request is the request def msg_connect(self, msg): print &quot;Connect message received&quot;, msg self.msg(&quot;connected&quot;, hello=&quot;world&quot;) def socketio_service(request): return Response( socketio_manage(ConnectIOContext(request)) )
  • But wait, there's more!
    • Events
    • i18n
    • Sessions
    • Hooks
    • ZCML
    • Includes
    • ZODB and SQLAlchemy
    • Https://convore.com/pylons
    • Http://docs.pylonsproject.org/docs/pyramid.html
    • Https://github.com/Pylons
    • Http://pylonsproject.org
    • Dylan Jay
    • http://www.pretaweb.com