SlideShare une entreprise Scribd logo
1  sur  50
Télécharger pour lire hors ligne
Pyramid:A Drive-by
Tutorial
Paul Everitt@dcpython - Feb 5 2013
Friday, February 8, 13
I Am...
• Prehistoric
• Web, Python, Zope, Plone, Pyramid
• Agendaless Consulting with Chris and Tres,
Fredericksburg
• Manage large web projects...yep, I’m
pimping
Friday, February 8, 13
Why Pyramid?
Friday, February 8, 13
Friday, February 8, 13
Friday, February 8, 13
Friday, February 8, 13
What is Pyramid?
• Python (2 and 3) web framework
• Merger of repoze.bfg (from the Zope guys)
and Pylons
• Target audience: Projects that start small
and finish big
Friday, February 8, 13
Show Me The Money
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
def hello_world(request):
return Response('Hello')
def main():
config = Configurator()
config.add_route('hello', '/')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app()
return app
if __name__ == '__main__':
app = main()
server = make_server('0.0.0.0', 6547, app)
print ('Starting up server on http://localhost:6547')
server.serve_forever()
Friday, February 8, 13
What...what’s that print?
• print ('Starting up server on http://localhost:6547')
• Yep, we’re going to do this on Python 3.3
Tutorial walkthrough at:
https://github.com/pauleveritt/dcpython
Friday, February 8, 13
Goals of Pyramid
Friday, February 8, 13
Only Pay For WhatYou
Eat
• Easy to start
• Few choices forced on you
• Small codebase
Friday, February 8, 13
Quality
Friday, February 8, 13
Quality
• Full test and docs coverage (culture of docs
and tests)
• Performance, profiling
Friday, February 8, 13
Small to Big
• Starting point and finishing point
• Unique features that let you scale your
design (configuration, events, custom
renderers, view predicates, traversal, ...)
Friday, February 8, 13
Back to 3.3
Friday, February 8, 13
Setting UpYour
virtualenv
$ wget http://python-distribute.org/distribute_setup.py
$ pyvenv-3.3 env33
$ env33/bin/python3.3 distribute_setup.py
$ env33/bin/easy_install-3.3 pip
Friday, February 8, 13
Installing and Running
Pyramid
$ env33/bin/pip-3.3 install pyramid
....chuggalugga...
$ env33/bin/python3.3 hello.py
Friday, February 8, 13
Boring
• Single-file “applications” are possible
• Just not the target
• Let’s do a simple package
Friday, February 8, 13
2: Hello Package
• setup.py
• tutorial/
• __init__.py
• helloworld.py
• views.py
Friday, February 8, 13
02: setup.py
from setuptools import setup
requires = [
'pyramid',
]
setup(name='tutorial',
entry_points="""
[paste.app_factory]
main = tutorial:main
""",
)
Friday, February 8, 13
02: __ini__.py
# package
Friday, February 8, 13
02: helloworld.py
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
def main():
config = Configurator()
config.add_route('hello', '/')
config.scan('views')
app = config.make_wsgi_app()
return app
if __name__ == '__main__':
app = main()
server = make_server('0.0.0.0', 6547, app)
print ('Starting up server on http://localhost:6547')
server.serve_forever()
Friday, February 8, 13
02: views
from pyramid.response import Response
from pyramid.view import view_config
@view_config(route_name='hello')
def hello_world(request):
return Response('Hello')
Friday, February 8, 13
03: Pyramid
Configuration
• .ini files
• pserve (and friends)
Friday, February 8, 13
03: development.ini[app:main]
use = egg:tutorial
pyramid.reload_templates = true
[server:main]
use = egg:pyramid#wsgiref
host = 0.0.0.0
port = 6543
[loggers]
keys = root
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
Friday, February 8, 13
03: __init__.py
from pyramid.config import Configurator
def main(global_config, **settings):
config = Configurator(settings=settings)
config.add_route('hello', '/')
config.scan()
return config.make_wsgi_app()
Friday, February 8, 13
04: Running
$ pserve development.ini --reload
Starting server in PID 32130.
Starting HTTP server on http://0.0.0.0:6547
127.0.0.1 - - [03/Feb/2013 20:03:58] "GET / HTTP/1.1" 200 5
Friday, February 8, 13
Yikes! Culture of
Testing!
• $ pip-3.3 install nose WebTest
Friday, February 8, 13
04: tests.py
import unittest
from pyramid import testing
classViewTests(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
def tearDown(self):
testing.tearDown()
def test_my_view(self):
from tutorial.views import hello_world
request = testing.DummyRequest()
response = hello_world(request)
self.assertEqual(response.status, '200 OK')
# ....con’t
class FunctionalTests(unittest.TestCase):
def setUp(self):
from tutorial import main
settings = {}
app = main(settings)
from webtest import TestApp
self.testapp = TestApp(app)
def test_it(self):
res = self.testapp.get('/', status=200)
self.assertIn(b'Hello', res.body)
Friday, February 8, 13
04:Test Running
$ nosetests .
..
----------------------------------------------------------------------
Ran 2 tests in 0.498s
OK
Friday, February 8, 13
05: Let’s Do a Template
• Change our view to use a “renderer”
• In this case, a template
• Makes test-writing better
• tutorial/templates/
• helloworld.pt
Friday, February 8, 13
05: views.py
from pyramid.view import view_config
@view_config(route_name='hello', renderer='templates/helloworld.pt')
def hello_world(request):
return dict(title='Hello World')
Friday, February 8, 13
05: templates/helloworld.pt
<html>
<head>
<title>${title}</title>
</head>
<body>
<div>
<h1>${title}</h1>
</div>
</body>
</html>
Friday, February 8, 13
05: tests.py
import unittest
from pyramid import testing
classViewTests(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
def tearDown(self):
testing.tearDown()
def test_my_view(self):
from tutorial.views import hello_world
request = testing.DummyRequest()
response = hello_world(request)
self.assertEqual(response['title'],
'Hello World')
class FunctionalTests(unittest.TestCase):
def setUp(self):
from tutorial import main
settings = {}
app = main(settings)
from webtest import TestApp
self.testapp = TestApp(app)
def test_it(self):
res = self.testapp.get('/', status=200)
self.assertIn(b'Hello World', res.body)
Friday, February 8, 13
06:View Classes
Friday, February 8, 13
06: views.py
from pyramid.view import view_config
class HelloWorld(object):
def __init__(self, request):
self.request = request
@view_config(route_name='hello',
renderer='templates/helloworld.pt')
def hello_world(self):
return dict(title='Hello World')
Friday, February 8, 13
06: tests.py
def test_my_view(self):
from tutorial.views import HelloWorld
request = testing.DummyRequest()
inst = HelloWorld(request)
response = inst.hello_world()
self.assertEqual(response['title'],
'Hello World')
Friday, February 8, 13
07: Static Assets
• tutorial/static/
• hello.css
• logo.png
Friday, February 8, 13
07: __init__.py
from pyramid.config import Configurator
def main(global_config, **settings):
config = Configurator(settings=settings)
config.add_route('hello', '/')
config.add_static_view(name='static', path='tutorial:static')
config.scan()
return config.make_wsgi_app()
Friday, February 8, 13
07: helloworld.pt
<html>
<head>
<title>${title}</title>
<link rel="stylesheet"
href="${request.static_url('tutorial:static/hello.css')}"/>
</head>
<body>
<div>
<h1>${title}</h1>
<p>
<img src="${request.static_url('tutorial:static/logo.png')}"
alt="Logo"/>
</p>
</div>
</body>
</html>
Friday, February 8, 13
08: Forms
• Use Deform for CRUD (with Colander and
Peppercorn)
• $ pip install deform
• deform_bootstrap optional
• Several other form libraries for Pyramid
• This step is ONLY rendering
Friday, February 8, 13
08: views.py
import colander
import deform
from pyramid.view import view_config
class Person(colander.MappingSchema):
name = colander.SchemaNode(colander.String())
age = colander.SchemaNode(colander.Integer(),
validator=colander.Range(0, 200))
class HelloWorld(object):
def __init__(self, request):
self.request = request
@view_config(route_name='hello',
renderer='templates/helloworld.pt')
def hello_world(self):
schema = Person()
form = deform.Form(schema, buttons=('submit',))
return dict(title='Hello World', form=form,
reqts=form.get_widget_resources())
Friday, February 8, 13
08: helloworld.pt
<html>
<head>
<title>${title}</title>
<link rel="stylesheet"
href="${request.static_url('tutorial:static/hello.css')}"/>
<tal:block repeat="reqt reqts['css']|[]">
<link rel="stylesheet" type="text/css"
href="${request.static_url('deform:static/' + reqt)}"/>
</tal:block>
<tal:block repeat="reqt reqts['js']|[]">
<script src="${request.static_url('deform:static/' + reqt)}"
type="text/javascript"></script>
</tal:block>
</head>
<body>
<div>
<h1><img src="${request.static_url('tutorial:static/logo.png')}"
alt="Logo"/>${title}</h1>
<p tal:content="structure form.render()">
</p>
</div>
</body>
</html>
Friday, February 8, 13
08: __init__.py
from pyramid.config import Configurator
def main(global_config, **settings):
config = Configurator(settings=settings)
config.add_route('hello', '/')
config.add_static_view(name='static', path='tutorial:static')
config.add_static_view('deform_static', 'deform:static/')
config.scan()
return config.make_wsgi_app()
Friday, February 8, 13
09: FormValidation
Friday, February 8, 13
09: views.py
import colander
import deform
from pyramid.decorator import reify
from pyramid.view import view_config, view_defaults
class Person(colander.MappingSchema):
name = colander.SchemaNode(colander.String())
age = colander.SchemaNode(colander.Integer(),
validator=colander.Range(0, 200))
@view_defaults(route_name='hello',
renderer='templates/helloworld.pt')
class HelloWorld(object):
title = 'Hello World'
status_message = None
def __init__(self, request):
self.request = request
@reify
def form(self):
schema = Person()
return deform.Form(schema, buttons=('submit',))
@reify
def reqts(self):
reqts = self.form.get_widget_resources()
return dict(
js_links=reqts.get('js', []),
css_links=reqts.get('css', [])
)
Friday, February 8, 13
09: views.py
@view_defaults(route_name='hello',
renderer='templates/helloworld.pt')
class HelloWorld(object):
title = 'Hello World'
status_message = None
@view_config()
def hello_world(self):
return dict(form=self.form)
@view_config(request_param='submit')
def submit_handler(self):
form = self.form
controls = self.request.POST.items()
try:
appstruct = form.validate(controls)
except deform.ValidationFailure as e:
return dict(form=e)
## Process the valid form data
self.status_message = 'Added person: ' + appstruct['name']
return dict(form=form, appstruct=appstruct)
Friday, February 8, 13
09: helloworld.pt
<html>
<head>
<title>${view.title}</title>
<link rel="stylesheet"
href="${request.static_url('tutorial:static/hello.css')}"/>
<tal:block repeat="reqt view.reqts['css_links']">
<link rel="stylesheet" type="text/css"
href="${request.static_url('deform:static/' + reqt)}"/>
</tal:block>
<tal:block repeat="reqt view.reqts['js_links']">
<script src="${request.static_url('deform:static/' + reqt)}"
type="text/javascript"></script>
</tal:block>
</head>
<body>
<div>
<h1><img src="${request.static_url('tutorial:static/logo.png')}"
alt="Logo"/>${view.title}</h1>
<p tal:condition="view.status_message">
<em>${view.status_message}</em>
</p>
<p tal:content="structure form.render()">
</p>
</div>
</body>
</html>
Friday, February 8, 13
Validation
Friday, February 8, 13
...and more
• Other template languages
• SQLAlchemy (or others) for storage/
retrieval
• Authentication and authorization
• Sessions, events, i18n, resources and
traversal, advanced configuration, ...
• Substance D
Friday, February 8, 13

Contenu connexe

Tendances

Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Python Ireland
 
Meck at erlang factory, london 2011
Meck at erlang factory, london 2011Meck at erlang factory, london 2011
Meck at erlang factory, london 2011Adam Lindberg
 
2014_07_28_Django環境安裝以及 Django Book Chapter 4: Templates
2014_07_28_Django環境安裝以及 Django Book Chapter 4: Templates2014_07_28_Django環境安裝以及 Django Book Chapter 4: Templates
2014_07_28_Django環境安裝以及 Django Book Chapter 4: TemplatesKe Wei Louis
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRJavier Abadía
 
Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryMauro Rocco
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterHaehnchen
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.jsMatthew Beale
 
Behind the curtain - How Django handles a request
Behind the curtain - How Django handles a requestBehind the curtain - How Django handles a request
Behind the curtain - How Django handles a requestDaniel Hepper
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersDavid Rodenas
 
More android code puzzles
More android code puzzlesMore android code puzzles
More android code puzzlesDanny Preussler
 
WordPress plugin #2
WordPress plugin #2WordPress plugin #2
WordPress plugin #2giwoolee
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming Enguest9bcef2f
 
Ditching JQuery
Ditching JQueryDitching JQuery
Ditching JQueryhowlowck
 
Django’s nasal passage
Django’s nasal passageDjango’s nasal passage
Django’s nasal passageErik Rose
 
Testing Ember Apps: Managing Dependency
Testing Ember Apps: Managing DependencyTesting Ember Apps: Managing Dependency
Testing Ember Apps: Managing DependencyMatthew Beale
 

Tendances (19)

Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)
 
Meck at erlang factory, london 2011
Meck at erlang factory, london 2011Meck at erlang factory, london 2011
Meck at erlang factory, london 2011
 
2014_07_28_Django環境安裝以及 Django Book Chapter 4: Templates
2014_07_28_Django環境安裝以及 Django Book Chapter 4: Templates2014_07_28_Django環境安裝以及 Django Book Chapter 4: Templates
2014_07_28_Django環境安裝以及 Django Book Chapter 4: Templates
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
 
Gae
GaeGae
Gae
 
Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & Celery
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
Meck
MeckMeck
Meck
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.js
 
Behind the curtain - How Django handles a request
Behind the curtain - How Django handles a requestBehind the curtain - How Django handles a request
Behind the curtain - How Django handles a request
 
Vuejs testing
Vuejs testingVuejs testing
Vuejs testing
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
 
More android code puzzles
More android code puzzlesMore android code puzzles
More android code puzzles
 
WordPress plugin #2
WordPress plugin #2WordPress plugin #2
WordPress plugin #2
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
 
Ditching JQuery
Ditching JQueryDitching JQuery
Ditching JQuery
 
Django’s nasal passage
Django’s nasal passageDjango’s nasal passage
Django’s nasal passage
 
Your code are my tests
Your code are my testsYour code are my tests
Your code are my tests
 
Testing Ember Apps: Managing Dependency
Testing Ember Apps: Managing DependencyTesting Ember Apps: Managing Dependency
Testing Ember Apps: Managing Dependency
 

Similaire à Pyramiddcpythonfeb2013 131006105131-phpapp02

Pyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web appsPyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web appsDylan Jay
 
How to host an app for $20 in 20min using buildout and hostout
How to host an app  for $20 in 20min using buildout and hostoutHow to host an app  for $20 in 20min using buildout and hostout
How to host an app for $20 in 20min using buildout and hostoutDylan Jay
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexyananelson
 
Intro to Pylons / Pyramid
Intro to Pylons / PyramidIntro to Pylons / Pyramid
Intro to Pylons / PyramidEric Paxton
 
Django for mobile applications
Django for mobile applicationsDjango for mobile applications
Django for mobile applicationsHassan Abid
 
Vue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapyVue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapyDarío Blanco Iturriaga
 
Introduction to Zend framework
Introduction to Zend framework Introduction to Zend framework
Introduction to Zend framework Matteo Magni
 
Building a Dynamic Website Using Django
Building a Dynamic Website Using DjangoBuilding a Dynamic Website Using Django
Building a Dynamic Website Using DjangoNathan Eror
 
Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long jaxconf
 
Effective testing with pytest
Effective testing with pytestEffective testing with pytest
Effective testing with pytestHector Canto
 
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...DicodingEvent
 
Dependency Injection @ AngularJS
Dependency Injection @ AngularJSDependency Injection @ AngularJS
Dependency Injection @ AngularJSRan Mizrahi
 
Building a Django App on Heroku
Building a Django App on HerokuBuilding a Django App on Heroku
Building a Django App on HerokuJoe Fusaro
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introductionNir Kaufman
 

Similaire à Pyramiddcpythonfeb2013 131006105131-phpapp02 (20)

Pyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web appsPyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web apps
 
How to host an app for $20 in 20min using buildout and hostout
How to host an app  for $20 in 20min using buildout and hostoutHow to host an app  for $20 in 20min using buildout and hostout
How to host an app for $20 in 20min using buildout and hostout
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexy
 
Backbone
BackboneBackbone
Backbone
 
Intro to Pylons / Pyramid
Intro to Pylons / PyramidIntro to Pylons / Pyramid
Intro to Pylons / Pyramid
 
Complex Sites with Silex
Complex Sites with SilexComplex Sites with Silex
Complex Sites with Silex
 
Django for mobile applications
Django for mobile applicationsDjango for mobile applications
Django for mobile applications
 
Vue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapyVue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapy
 
Introduction to Zend framework
Introduction to Zend framework Introduction to Zend framework
Introduction to Zend framework
 
NestJS
NestJSNestJS
NestJS
 
Building a Dynamic Website Using Django
Building a Dynamic Website Using DjangoBuilding a Dynamic Website Using Django
Building a Dynamic Website Using Django
 
Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long Multi Client Development with Spring - Josh Long
Multi Client Development with Spring - Josh Long
 
Effective testing with pytest
Effective testing with pytestEffective testing with pytest
Effective testing with pytest
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
 
Dependency Injection @ AngularJS
Dependency Injection @ AngularJSDependency Injection @ AngularJS
Dependency Injection @ AngularJS
 
Building a Django App on Heroku
Building a Django App on HerokuBuilding a Django App on Heroku
Building a Django App on Heroku
 
Python at Facebook
Python at FacebookPython at Facebook
Python at Facebook
 
Celery
CeleryCelery
Celery
 
Angularjs - Unit testing introduction
Angularjs - Unit testing introductionAngularjs - Unit testing introduction
Angularjs - Unit testing introduction
 

Plus de Jeffrey Clark

Python memory management_v2
Python memory management_v2Python memory management_v2
Python memory management_v2Jeffrey Clark
 
Jwt with flask slide deck - alan swenson
Jwt with flask   slide deck - alan swensonJwt with flask   slide deck - alan swenson
Jwt with flask slide deck - alan swensonJeffrey Clark
 
Genericmeetupslides 110607190400-phpapp02
Genericmeetupslides 110607190400-phpapp02Genericmeetupslides 110607190400-phpapp02
Genericmeetupslides 110607190400-phpapp02Jeffrey Clark
 
Zpugdc2007 101105081808-phpapp01
Zpugdc2007 101105081808-phpapp01Zpugdc2007 101105081808-phpapp01
Zpugdc2007 101105081808-phpapp01Jeffrey Clark
 
Zpugdc deformpresentation-100709203803-phpapp01
Zpugdc deformpresentation-100709203803-phpapp01Zpugdc deformpresentation-100709203803-phpapp01
Zpugdc deformpresentation-100709203803-phpapp01Jeffrey Clark
 
Zpugdccherry 101105081729-phpapp01
Zpugdccherry 101105081729-phpapp01Zpugdccherry 101105081729-phpapp01
Zpugdccherry 101105081729-phpapp01Jeffrey Clark
 
Using Grok to Walk Like a Duck - Brandon Craig Rhodes
Using Grok to Walk Like a Duck - Brandon Craig RhodesUsing Grok to Walk Like a Duck - Brandon Craig Rhodes
Using Grok to Walk Like a Duck - Brandon Craig RhodesJeffrey Clark
 
What Makes A Great Dev Team - Mike Robinson
What Makes A Great Dev Team - Mike RobinsonWhat Makes A Great Dev Team - Mike Robinson
What Makes A Great Dev Team - Mike RobinsonJeffrey Clark
 
What Makes A Great Dev Team - Mike Robinson
What Makes A Great Dev Team - Mike RobinsonWhat Makes A Great Dev Team - Mike Robinson
What Makes A Great Dev Team - Mike RobinsonJeffrey Clark
 
Plone I18n Tutorial - Hanno Schlichting
Plone I18n Tutorial - Hanno SchlichtingPlone I18n Tutorial - Hanno Schlichting
Plone I18n Tutorial - Hanno SchlichtingJeffrey Clark
 
Real World Intranets - Joel Burton
Real World Intranets - Joel BurtonReal World Intranets - Joel Burton
Real World Intranets - Joel BurtonJeffrey Clark
 
State Of Zope 3 - Stephan Richter
State Of Zope 3 - Stephan RichterState Of Zope 3 - Stephan Richter
State Of Zope 3 - Stephan RichterJeffrey Clark
 
KSS Techniques - Joel Burton
KSS Techniques - Joel BurtonKSS Techniques - Joel Burton
KSS Techniques - Joel BurtonJeffrey Clark
 

Plus de Jeffrey Clark (20)

Python memory management_v2
Python memory management_v2Python memory management_v2
Python memory management_v2
 
Python meetup
Python meetupPython meetup
Python meetup
 
Jwt with flask slide deck - alan swenson
Jwt with flask   slide deck - alan swensonJwt with flask   slide deck - alan swenson
Jwt with flask slide deck - alan swenson
 
Genericmeetupslides 110607190400-phpapp02
Genericmeetupslides 110607190400-phpapp02Genericmeetupslides 110607190400-phpapp02
Genericmeetupslides 110607190400-phpapp02
 
Dc python meetup
Dc python meetupDc python meetup
Dc python meetup
 
Zpugdc2007 101105081808-phpapp01
Zpugdc2007 101105081808-phpapp01Zpugdc2007 101105081808-phpapp01
Zpugdc2007 101105081808-phpapp01
 
Zpugdc deformpresentation-100709203803-phpapp01
Zpugdc deformpresentation-100709203803-phpapp01Zpugdc deformpresentation-100709203803-phpapp01
Zpugdc deformpresentation-100709203803-phpapp01
 
Zpugdccherry 101105081729-phpapp01
Zpugdccherry 101105081729-phpapp01Zpugdccherry 101105081729-phpapp01
Zpugdccherry 101105081729-phpapp01
 
Tornado
TornadoTornado
Tornado
 
Science To Bfg
Science To BfgScience To Bfg
Science To Bfg
 
The PSF and You
The PSF and YouThe PSF and You
The PSF and You
 
Using Grok to Walk Like a Duck - Brandon Craig Rhodes
Using Grok to Walk Like a Duck - Brandon Craig RhodesUsing Grok to Walk Like a Duck - Brandon Craig Rhodes
Using Grok to Walk Like a Duck - Brandon Craig Rhodes
 
What Makes A Great Dev Team - Mike Robinson
What Makes A Great Dev Team - Mike RobinsonWhat Makes A Great Dev Team - Mike Robinson
What Makes A Great Dev Team - Mike Robinson
 
What Makes A Great Dev Team - Mike Robinson
What Makes A Great Dev Team - Mike RobinsonWhat Makes A Great Dev Team - Mike Robinson
What Makes A Great Dev Team - Mike Robinson
 
Plone I18n Tutorial - Hanno Schlichting
Plone I18n Tutorial - Hanno SchlichtingPlone I18n Tutorial - Hanno Schlichting
Plone I18n Tutorial - Hanno Schlichting
 
Real World Intranets - Joel Burton
Real World Intranets - Joel BurtonReal World Intranets - Joel Burton
Real World Intranets - Joel Burton
 
State Of Zope 3 - Stephan Richter
State Of Zope 3 - Stephan RichterState Of Zope 3 - Stephan Richter
State Of Zope 3 - Stephan Richter
 
KSS Techniques - Joel Burton
KSS Techniques - Joel BurtonKSS Techniques - Joel Burton
KSS Techniques - Joel Burton
 
Zenoss: Buildout
Zenoss: BuildoutZenoss: Buildout
Zenoss: Buildout
 
Opensourceweblion
OpensourceweblionOpensourceweblion
Opensourceweblion
 

Dernier

Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 

Dernier (20)

Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 

Pyramiddcpythonfeb2013 131006105131-phpapp02

  • 1. Pyramid:A Drive-by Tutorial Paul Everitt@dcpython - Feb 5 2013 Friday, February 8, 13
  • 2. I Am... • Prehistoric • Web, Python, Zope, Plone, Pyramid • Agendaless Consulting with Chris and Tres, Fredericksburg • Manage large web projects...yep, I’m pimping Friday, February 8, 13
  • 7. What is Pyramid? • Python (2 and 3) web framework • Merger of repoze.bfg (from the Zope guys) and Pylons • Target audience: Projects that start small and finish big Friday, February 8, 13
  • 8. Show Me The Money from wsgiref.simple_server import make_server from pyramid.config import Configurator from pyramid.response import Response def hello_world(request): return Response('Hello') def main(): config = Configurator() config.add_route('hello', '/') config.add_view(hello_world, route_name='hello') app = config.make_wsgi_app() return app if __name__ == '__main__': app = main() server = make_server('0.0.0.0', 6547, app) print ('Starting up server on http://localhost:6547') server.serve_forever() Friday, February 8, 13
  • 9. What...what’s that print? • print ('Starting up server on http://localhost:6547') • Yep, we’re going to do this on Python 3.3 Tutorial walkthrough at: https://github.com/pauleveritt/dcpython Friday, February 8, 13
  • 10. Goals of Pyramid Friday, February 8, 13
  • 11. Only Pay For WhatYou Eat • Easy to start • Few choices forced on you • Small codebase Friday, February 8, 13
  • 13. Quality • Full test and docs coverage (culture of docs and tests) • Performance, profiling Friday, February 8, 13
  • 14. Small to Big • Starting point and finishing point • Unique features that let you scale your design (configuration, events, custom renderers, view predicates, traversal, ...) Friday, February 8, 13
  • 15. Back to 3.3 Friday, February 8, 13
  • 16. Setting UpYour virtualenv $ wget http://python-distribute.org/distribute_setup.py $ pyvenv-3.3 env33 $ env33/bin/python3.3 distribute_setup.py $ env33/bin/easy_install-3.3 pip Friday, February 8, 13
  • 17. Installing and Running Pyramid $ env33/bin/pip-3.3 install pyramid ....chuggalugga... $ env33/bin/python3.3 hello.py Friday, February 8, 13
  • 18. Boring • Single-file “applications” are possible • Just not the target • Let’s do a simple package Friday, February 8, 13
  • 19. 2: Hello Package • setup.py • tutorial/ • __init__.py • helloworld.py • views.py Friday, February 8, 13
  • 20. 02: setup.py from setuptools import setup requires = [ 'pyramid', ] setup(name='tutorial', entry_points=""" [paste.app_factory] main = tutorial:main """, ) Friday, February 8, 13
  • 22. 02: helloworld.py from wsgiref.simple_server import make_server from pyramid.config import Configurator def main(): config = Configurator() config.add_route('hello', '/') config.scan('views') app = config.make_wsgi_app() return app if __name__ == '__main__': app = main() server = make_server('0.0.0.0', 6547, app) print ('Starting up server on http://localhost:6547') server.serve_forever() Friday, February 8, 13
  • 23. 02: views from pyramid.response import Response from pyramid.view import view_config @view_config(route_name='hello') def hello_world(request): return Response('Hello') Friday, February 8, 13
  • 24. 03: Pyramid Configuration • .ini files • pserve (and friends) Friday, February 8, 13
  • 25. 03: development.ini[app:main] use = egg:tutorial pyramid.reload_templates = true [server:main] use = egg:pyramid#wsgiref host = 0.0.0.0 port = 6543 [loggers] keys = root [handlers] keys = console [formatters] keys = generic [logger_root] level = INFO handlers = console [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s Friday, February 8, 13
  • 26. 03: __init__.py from pyramid.config import Configurator def main(global_config, **settings): config = Configurator(settings=settings) config.add_route('hello', '/') config.scan() return config.make_wsgi_app() Friday, February 8, 13
  • 27. 04: Running $ pserve development.ini --reload Starting server in PID 32130. Starting HTTP server on http://0.0.0.0:6547 127.0.0.1 - - [03/Feb/2013 20:03:58] "GET / HTTP/1.1" 200 5 Friday, February 8, 13
  • 28. Yikes! Culture of Testing! • $ pip-3.3 install nose WebTest Friday, February 8, 13
  • 29. 04: tests.py import unittest from pyramid import testing classViewTests(unittest.TestCase): def setUp(self): self.config = testing.setUp() def tearDown(self): testing.tearDown() def test_my_view(self): from tutorial.views import hello_world request = testing.DummyRequest() response = hello_world(request) self.assertEqual(response.status, '200 OK') # ....con’t class FunctionalTests(unittest.TestCase): def setUp(self): from tutorial import main settings = {} app = main(settings) from webtest import TestApp self.testapp = TestApp(app) def test_it(self): res = self.testapp.get('/', status=200) self.assertIn(b'Hello', res.body) Friday, February 8, 13
  • 30. 04:Test Running $ nosetests . .. ---------------------------------------------------------------------- Ran 2 tests in 0.498s OK Friday, February 8, 13
  • 31. 05: Let’s Do a Template • Change our view to use a “renderer” • In this case, a template • Makes test-writing better • tutorial/templates/ • helloworld.pt Friday, February 8, 13
  • 32. 05: views.py from pyramid.view import view_config @view_config(route_name='hello', renderer='templates/helloworld.pt') def hello_world(request): return dict(title='Hello World') Friday, February 8, 13
  • 34. 05: tests.py import unittest from pyramid import testing classViewTests(unittest.TestCase): def setUp(self): self.config = testing.setUp() def tearDown(self): testing.tearDown() def test_my_view(self): from tutorial.views import hello_world request = testing.DummyRequest() response = hello_world(request) self.assertEqual(response['title'], 'Hello World') class FunctionalTests(unittest.TestCase): def setUp(self): from tutorial import main settings = {} app = main(settings) from webtest import TestApp self.testapp = TestApp(app) def test_it(self): res = self.testapp.get('/', status=200) self.assertIn(b'Hello World', res.body) Friday, February 8, 13
  • 36. 06: views.py from pyramid.view import view_config class HelloWorld(object): def __init__(self, request): self.request = request @view_config(route_name='hello', renderer='templates/helloworld.pt') def hello_world(self): return dict(title='Hello World') Friday, February 8, 13
  • 37. 06: tests.py def test_my_view(self): from tutorial.views import HelloWorld request = testing.DummyRequest() inst = HelloWorld(request) response = inst.hello_world() self.assertEqual(response['title'], 'Hello World') Friday, February 8, 13
  • 38. 07: Static Assets • tutorial/static/ • hello.css • logo.png Friday, February 8, 13
  • 39. 07: __init__.py from pyramid.config import Configurator def main(global_config, **settings): config = Configurator(settings=settings) config.add_route('hello', '/') config.add_static_view(name='static', path='tutorial:static') config.scan() return config.make_wsgi_app() Friday, February 8, 13
  • 41. 08: Forms • Use Deform for CRUD (with Colander and Peppercorn) • $ pip install deform • deform_bootstrap optional • Several other form libraries for Pyramid • This step is ONLY rendering Friday, February 8, 13
  • 42. 08: views.py import colander import deform from pyramid.view import view_config class Person(colander.MappingSchema): name = colander.SchemaNode(colander.String()) age = colander.SchemaNode(colander.Integer(), validator=colander.Range(0, 200)) class HelloWorld(object): def __init__(self, request): self.request = request @view_config(route_name='hello', renderer='templates/helloworld.pt') def hello_world(self): schema = Person() form = deform.Form(schema, buttons=('submit',)) return dict(title='Hello World', form=form, reqts=form.get_widget_resources()) Friday, February 8, 13
  • 43. 08: helloworld.pt <html> <head> <title>${title}</title> <link rel="stylesheet" href="${request.static_url('tutorial:static/hello.css')}"/> <tal:block repeat="reqt reqts['css']|[]"> <link rel="stylesheet" type="text/css" href="${request.static_url('deform:static/' + reqt)}"/> </tal:block> <tal:block repeat="reqt reqts['js']|[]"> <script src="${request.static_url('deform:static/' + reqt)}" type="text/javascript"></script> </tal:block> </head> <body> <div> <h1><img src="${request.static_url('tutorial:static/logo.png')}" alt="Logo"/>${title}</h1> <p tal:content="structure form.render()"> </p> </div> </body> </html> Friday, February 8, 13
  • 44. 08: __init__.py from pyramid.config import Configurator def main(global_config, **settings): config = Configurator(settings=settings) config.add_route('hello', '/') config.add_static_view(name='static', path='tutorial:static') config.add_static_view('deform_static', 'deform:static/') config.scan() return config.make_wsgi_app() Friday, February 8, 13
  • 46. 09: views.py import colander import deform from pyramid.decorator import reify from pyramid.view import view_config, view_defaults class Person(colander.MappingSchema): name = colander.SchemaNode(colander.String()) age = colander.SchemaNode(colander.Integer(), validator=colander.Range(0, 200)) @view_defaults(route_name='hello', renderer='templates/helloworld.pt') class HelloWorld(object): title = 'Hello World' status_message = None def __init__(self, request): self.request = request @reify def form(self): schema = Person() return deform.Form(schema, buttons=('submit',)) @reify def reqts(self): reqts = self.form.get_widget_resources() return dict( js_links=reqts.get('js', []), css_links=reqts.get('css', []) ) Friday, February 8, 13
  • 47. 09: views.py @view_defaults(route_name='hello', renderer='templates/helloworld.pt') class HelloWorld(object): title = 'Hello World' status_message = None @view_config() def hello_world(self): return dict(form=self.form) @view_config(request_param='submit') def submit_handler(self): form = self.form controls = self.request.POST.items() try: appstruct = form.validate(controls) except deform.ValidationFailure as e: return dict(form=e) ## Process the valid form data self.status_message = 'Added person: ' + appstruct['name'] return dict(form=form, appstruct=appstruct) Friday, February 8, 13
  • 48. 09: helloworld.pt <html> <head> <title>${view.title}</title> <link rel="stylesheet" href="${request.static_url('tutorial:static/hello.css')}"/> <tal:block repeat="reqt view.reqts['css_links']"> <link rel="stylesheet" type="text/css" href="${request.static_url('deform:static/' + reqt)}"/> </tal:block> <tal:block repeat="reqt view.reqts['js_links']"> <script src="${request.static_url('deform:static/' + reqt)}" type="text/javascript"></script> </tal:block> </head> <body> <div> <h1><img src="${request.static_url('tutorial:static/logo.png')}" alt="Logo"/>${view.title}</h1> <p tal:condition="view.status_message"> <em>${view.status_message}</em> </p> <p tal:content="structure form.render()"> </p> </div> </body> </html> Friday, February 8, 13
  • 50. ...and more • Other template languages • SQLAlchemy (or others) for storage/ retrieval • Authentication and authorization • Sessions, events, i18n, resources and traversal, advanced configuration, ... • Substance D Friday, February 8, 13