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-)  Re...
Who uses it <ul><li>It's still new
Karl Project
Aeterna Water – paperless sales system </li></ul><ul><ul><li>“How to build complex web applications having fun”
http://slidesha.re/mH9Lxa
1000 employees
No ORM = easy integrate with Plone
Less Magic. More simple </li></ul></ul>
 
From the minds on PretaWeb... PloneFactory Web installer for the worlds favourite Python CMS Coming 2011...
Differences... <ul><li>Non opinionated framework
Component Architecture
Packages (eggs)
Simpler and faster </li></ul>Pyramid Django Plone Not Opinionated Opinionated Structured (CMS) Very Simple Simple Complex ...
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 impo...
<ul>config.add_route('myroute', '/prefix/{one}/{two}') config.add_view(hello_world, route_name='myroute') foo/{baz}/{bar}*...
View Callables from pyramid.response import Response def hello_world(request): return Response('Hello world!') from pyrami...
Request / prefix/foo/bar?pref=red&pref=blue; def hello_world(request): assert 'blue' == request.params['pref'] assert ['re...
Renderers from pyramid.view import view_config @view_config(renderer='json') def hello_world(request): return {'content':'...
Templates from pyramid.renderers import render_to_response def sample_view(request): return render_to_response('templates/...
Templates from pyramid.renderers import render_to_response def sample_view(request): return render_to_response('templates/...
BYO Templating from mako.template import Template from pyramid.response import Response def make_view(request): template =...
Chameleon ZPT Templates <ul><li>Compiled to python – really fast
XHTML complaint
.pt files </li></ul><! DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot; http://www.w3.org/TR/xhtml1...
Static Assets config.add_static_view(name='static', path='/var/www/static') / static/main.css -> /var/www/static/main.css ...
Traversal
Traversal (Resource Location) Pattern allowing transitive and indirect view loockup Simplifies view code for complex apps ...
Upcoming SlideShare
Loading in …5
×

Pyramid Lighter/Faster/Better web apps

12,460 views
12,239 views

Published on

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

Published in: Technology, Business
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
12,460
On SlideShare
0
From Embeds
0
Number of Embeds
80
Actions
Shares
0
Downloads
48
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide

Pyramid Lighter/Faster/Better web apps

  1. 1. Lighter/faster/better web apps Dylan Jay CTO PretaWeb.com SyPy.org twitter: djay75
  2. 2. From the mind of Chris McDonough As seen in bearded of PyCon 2009 http://www.flickr.com/photos/termie/3392894269/
  3. 3. 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-)
  4. 4. Who uses it <ul><li>It's still new
  5. 5. Karl Project
  6. 6. Aeterna Water – paperless sales system </li></ul><ul><ul><li>“How to build complex web applications having fun”
  7. 7. http://slidesha.re/mH9Lxa
  8. 8. 1000 employees
  9. 9. No ORM = easy integrate with Plone
  10. 10. Less Magic. More simple </li></ul></ul>
  11. 12. From the minds on PretaWeb... PloneFactory Web installer for the worlds favourite Python CMS Coming 2011...
  12. 13. Differences... <ul><li>Non opinionated framework
  13. 14. Component Architecture
  14. 15. Packages (eggs)
  15. 16. Simpler and faster </li></ul>Pyramid Django Plone Not Opinionated Opinionated Structured (CMS) Very Simple Simple Complex No DB ORM Content Types Little Reuse Some Reuse Easy Reuse
  16. 17. Performance http://blog.curiasolutions.com/the-great-web-framework-shootout/
  17. 18. Performance http://plope.com/pyroptimization
  18. 19. Install $ virtualenv -- no-site-packages -- distribute newproject $ cd newproject $ bin/pip install pyramid
  19. 20. 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')
  20. 21. <ul>config.add_route('myroute', '/prefix/{one}/{two}') config.add_view(hello_world, route_name='myroute') foo/{baz}/{bar}*fizzle foo/{baz}/{bar}{fizzle:.*} <li>Also custom predicates </li></ul>Routes (URL Dispatch)
  21. 22. 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')
  22. 23. 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!')
  23. 24. 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')
  24. 25. 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)
  25. 26. 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)
  26. 27. 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
  27. 28. Chameleon ZPT Templates <ul><li>Compiled to python – really fast
  28. 29. XHTML complaint
  29. 30. .pt files </li></ul><! 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>
  30. 31. 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
  31. 32. Traversal
  32. 33. 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)
  33. 34. 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)
  34. 35. View Predicates <ul><li>name
  35. 36. context (class or interface)
  36. 37. route_name
  37. 38. request_type (interface)
  38. 39. request_method (e.g POST)
  39. 40. header </li></ul><ul><li>request_param (key in request.params)
  40. 41. containment (class or interface)
  41. 42. xhr
  42. 43. accept (mimetypes)
  43. 44. path_info (regex)
  44. 45. custom_predicates </li></ul>
  45. 46. 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')
  46. 47. 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)
  47. 48. 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'), ]
  48. 49. 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
  49. 50. Customising <ul><li>Designed Extensible
  50. 51. Not “apps” like django </li></ul><ul><li>Plugpoints </li></ul><ul><ul><li>Views
  51. 52. Routes
  52. 53. Assets </li></ul></ul>
  53. 54. 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')
  54. 55. 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)) )
  55. 56. But wait, there's more! <ul><li>Events
  56. 57. i18n
  57. 58. Sessions
  58. 59. Hooks
  59. 60. ZCML
  60. 61. Includes
  61. 62. ZODB and SQLAlchemy </li></ul>
  62. 63. <ul><li>Https://convore.com/pylons
  63. 64. Http://docs.pylonsproject.org/docs/pyramid.html
  64. 65. Https://github.com/Pylons
  65. 66. Http://pylonsproject.org
  66. 67. Dylan Jay
  67. 68. http://www.pretaweb.com </li></ul>

×