SlideShare uma empresa Scribd logo
1 de 26
Baixar para ler offline
Pluggable Applications with
      TurboGears2
  Using TurboGears2 pluggable applications




                 Alessandro Molina
                    @__amol__
TurboGears2
● Framework for rapid development encouraging
  customization

● Object Dispatch based, regular expressions can get messy,
  you will never have to write one anymore

● By default an XML template engine with error detection

● Declarative Models with transactional unit of work

● Built in Validation, Authentication, Authorization, Caching,
   Sessions, Migrations, MongoDB Support and many more.
OverView

CONTROLLER                                 TEMPLATE
class RootController(BaseController):      <html xmlns="http://www.w3.org/1999/xhtml"
  error = ErrorController()                   xmlns:py="http://genshi.edgewall.org/"
                                              xmlns:xi="http://www.w3.org/2001/XInclude">
  @expose('wiki20.templates.index')
  def index(self):                          <xi:include href="master.html" />
    return dict(page='index')
                                           <head>
                                            <title>My Title</title>
                                           </head>
MODEL
                                           <body>
class Page(DeclarativeBase):                 <h1>${page}</h1>
  __tablename__ = 'pages'                    <div py:for="num in range(10)">${num}</div>
                                           </body>
  id = Column(Integer, primary_key=True)   </html>
  pagename = Column(Text, unique=True)
  data = Column(Text)
Object Dispatch
                                                       URL                     CONTROLLER
class BlogEntryController(BaseController):
  @expose()
  def index(self, post):
    return 'HI'                              /index                RootController.index
 @expose()
 def edit(self, post):
   return 'HI'                               /                     RootController.index
 @expose()
 def update(self, post):
   return 'HI'                               /blog/3               BlogEntryController.index
                                                                   (post = 3)
class RootController(BaseController):
  blog = BlogEntryController()               /blog/update?post=3   BlogEntryController.update
                                                                   (post = 3)
  @expose()
  def index(self):
    return 'HI'                              /about                RootController.about

 @expose()
 def about(self):
                                             /more/1/2/3           RootController.more
   return 'HI'
                                                                   (args[0]=1, args[1]=2, args[3]=3)
 @expose()
 def more(self, *args, **kw):                /more?data=5          RootController.more
   return 'HI'
                                                                   (kw['data']=5)
Declarative Model
current_page = DBSession.query(Page).filter_by(pagename='index').first()
pages = DBSession.query(Page).all()
subpages = DBSession.query(Page).filter(Page.pagename.like('index_%')).all()




TurboGears does this for us if              DBSession.add(Page(pagename='index_about',
no errors appeared during the                                    data='About Content'))
request. The Unit of Work will              DBSession.flush()
reorder insertions as required              transaction.commit()
by dependencies.




TurboGears will automatically commit transactions on any session used inside the request if no error
appears, otherwise a rollback is issued to avoid messing up the database.
Genshi XML templating
<!DOCTYPE html>                                                     ●    Validated, if there is any error in the template
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:py="http://genshi.edgewall.org/">
                                                                         structure it will be reported
 <head>
  <title>Geddit: News</title>                                       ●    XML based, just a bunch of attributes to your
 </head>
 <body class="index">                                                    tags, this makes possible to edit the
  <div id="header">                                                      templates with wysiwyg editors
   <h1>News</h1>
  </div>
                                                                    ●    Conditional tags
  <ol py:if="links">
   <li py:for="link in reversed(links)">
    <a href="${link.url}">${link.title}</a>                         ●    Tags content iteration
    posted by ${link.username} at ${link.time.strftime('%x %X')}
   </li>
  </ol>
                                                                    ●    Variables substitution with escaping

  <p><a class="action" href="/submit/">Submit new link</a></p>      ●    Templates inheritance
  <div id="footer">
    <hr />
    <p class="legalese">© 2007 Edgewall Software</p>
  </div>
 </body>
</html>                                                            Not so fast, if you want superfast templating
                                                                   TurboGears offers Mako support builtin.
                                                                   Mako is not validated and xml editors friendly but it
                                                                   is superfast.
Quickstarting an Application
                $ virtualenv --no-site-packages -p python2.6 tg2env
                $ cd tg2env/
                $ source bin/activate
                (tg2env)$ easy_install -i http://tg.gy/current tg.devtools
                (tg2env)$ paster quickstart example
                (tg2env)$ cd example/
                (tg2env)$ python setup.py develop
                (tg2env)$ paster setup-app development.ini
                (tg2env)$ paster serve development.ini

●   We use a virtual environment not to mess with our system wide packages
●   Using TurboGears private index will permit to install the exact right version of the packages
●   The quickstart command will create for us a new project with authentication, authorization and
    models.
●   We use the setup.py develop command to install the project to be able to run it
●   The setup-app command will initialize the database with a bunch of users for us, we can avoid this
    if we choose not to enable authentication
●   Last we can call the serve command to run out application
Explore Quickstart
Sample Project

● Personal Website

● with Photo Galleries

● a Blog

● and many Wiki like pages
Photo Galleries
                                                 Install tgapp-photos pluggable
(tg2env)$ easy_install tgapp-photos              applications for photo albums support
(tg2env)$ mkdir example/public/attachments

from tgext.pluggable import plug                 We Plug tgapp-photos to have ready to
plug(base_config, 'photos')                      use photo albums support


<body>
 <div id="getting_started">
   ${h.call_partial('photos.partials:albums')}   Our Template ends being just a call to
                                                 the partial that renders the previews of
    <div style="clear:both"/>                    our albums
 </div>
</body>

.photos_gallery {
     display: block;
     float: left;                                Some CSS to give a minimal look to our
                                                 gallery
     text-align: center;
     margin-left: 10px;
     margin-bottom: 10px;
 }
Our Photo galleries




        Argh, it look awful...
       But this is why CSS exist
I want my blog, Now !
                                                         Install tgapp-smallpress for blogs
(tg2env)$ easy_install tgapp-smallpress                  support and create a directory
                                                         where it can store attachments

from tgext.pluggable import plug                       We Plug tgapp-photos to have
plug(base_config, 'photos')                            ready to use photo albums
                                                       support

<body>
 <div id="getting_started">
   ${h.call_partial('photos.partials:albums')}         Add call to smallpress partial to
    <div style="clear:both"/>                          render the list of articles of the
   ${h.call_partial('smallpress.partials:articles')}   default blog
 </div>
</body>

#smallpress_articles { margin-top: 30px; }
.smallpress_article h2 { margin-bottom: 0; }             Our usual bunch of minimal styling.
.smallpress_article h2 a { text-decoration: none; }
.smallpress_article h4 { margin-top: 0; }
Well, somehow it works
What about the other pages?
What's up with those About, Authentication,
WSGI and Contact pages? We don't need them
for our personal website!

Let's remove all the methods in
RootController between index and login
and their templates!
Doh!




Well, actually we need to remove also the links
inside the menu bar. Those are defined into
master.html which is the master template
that every page inherits.
Let's now add wiki to our site
First of all our model, it's just a page with a title
and a content.

from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.types import Unicode, Integer, DateTime, Text
from sqlalchemy.orm import relation, synonym

from example.model import DeclarativeBase

class WikiPage(DeclarativeBase):
  __tablename__ = 'wikipages'

  uid = Column(Integer, primary_key=True)
  pagename = Column(Text, unique=True)
  data = Column(Text)
Let our pages exist
First of all we need to make our WikiPage
model available inside the model module:
from example.model.wiki import WikiPage




Then run setup-app again so that our new
table get created.
(tg2env)$ paster setup-app development.ini
Time for some magic

from tgext.crud import EasyCrudRestController

class WikiController(EasyCrudRestController):
  model = model.WikiPage

class RootController(BaseController):
  pages = WikiController(DBSession)
  [...]
Works out of the box




CRUD did all the work for us, now we just have
to create our wiki pages!
Fetch the pages for our menu
_before method get called before calling every
controller method and tmpl_context is the
TurboGears template context, which is always
available inside a request.

from tg import tmpl_context

class RootController(BaseController):
  pages = WikiController(DBSession)

  def _before(self, *args, **kw):
    tmpl_context.pages = DBSession.query(model.WikiPage).all()
Let's draw our menu
Inside master.html mainmenu add links for
our pages

<li py:for="page in getattr(tmpl_context, 'pages', [])">
   <a href="${'/%s' % page.pagename}">${page.pagename}</a>
</li>
Doh!




Again?!
Well our website yet doesn't know how to
display our wiki pages
Serving our wiki pages
from webob.exc import HTTPNotFound
from webhelpers.markdown import Markdown
class RootController(BaseController):
   pages = WikiController(DBSession)

  def _before(self, *args, **kw):
                                                                       _default method gets
    tmpl_context.pages = DBSession.query(model.WikiPage).all()         executed every time Object
                                                                       Dispatch is able to resolve
  @expose('example.templates.index')                                   the url only up to the
  def index(self):                                                     controller but is not able to
    return dict(page='index')                                          find a method that matches
                                                                       the url
  @expose('example.templates.page')
  def _default(self, *args, **kw):
    page = None
    if args:
       page = DBSession.query(model.WikiPage).filter_by(pagename=args[0]).first()

    if not page:
       raise HTTPNotFound

    return dict(page=page.pagename, content=Markdown(page.data).convert())
example.templates.page
Very little to do, just show a title and its
content.

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:xi="http://www.w3.org/2001/XInclude">

<xi:include href="master.html" />

 <head>
  <title>${page}</title>                            Markup is required to tell Genshi that the
 </head>                                            value should not be escaped.

 <body>                                             webhelpers.Markdown generated nice
  <h1>${page}</h1>                                  HTML for us and we want to show the
  ${Markup(content)}                                rendering not the HTML itself!
 </body>
</html>
Woh! It works!




Our website is ready! Now we can add any
number of pages using the Markdown syntax.
Have Fun!
TurboGears2, its crud and pluggable
applications can make as easy as 1,2,3 creating
a web application, just open your editor and
have fun!




                   http://www.turbogears.org

Mais conteúdo relacionado

Mais procurados

Getting Into Drupal 8 Configuration
Getting Into Drupal 8 ConfigurationGetting Into Drupal 8 Configuration
Getting Into Drupal 8 ConfigurationPhilip Norton
 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionPhilip Norton
 
Getting to The Loop - London Wordpress Meetup July 28th
Getting to The Loop - London Wordpress Meetup  July 28thGetting to The Loop - London Wordpress Meetup  July 28th
Getting to The Loop - London Wordpress Meetup July 28thChris Adams
 
WordPress plugin #2
WordPress plugin #2WordPress plugin #2
WordPress plugin #2giwoolee
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)arcware
 
Angular JS blog tutorial
Angular JS blog tutorialAngular JS blog tutorial
Angular JS blog tutorialClaude Tech
 
#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...탑크리에듀(구로디지털단지역3번출구 2분거리)
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceParashuram N
 
Using of TDD practices for Magento
Using of TDD practices for MagentoUsing of TDD practices for Magento
Using of TDD practices for MagentoIvan Chepurnyi
 
Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4DEVCON
 
Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4DEVCON
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of DjangoJacob Kaplan-Moss
 
Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Ivan Chepurnyi
 
JavaScript
JavaScriptJavaScript
JavaScriptSunil OS
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4DEVCON
 

Mais procurados (20)

Getting Into Drupal 8 Configuration
Getting Into Drupal 8 ConfigurationGetting Into Drupal 8 Configuration
Getting Into Drupal 8 Configuration
 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency Injection
 
Getting to The Loop - London Wordpress Meetup July 28th
Getting to The Loop - London Wordpress Meetup  July 28thGetting to The Loop - London Wordpress Meetup  July 28th
Getting to The Loop - London Wordpress Meetup July 28th
 
WordPress plugin #2
WordPress plugin #2WordPress plugin #2
WordPress plugin #2
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
Angular JS blog tutorial
Angular JS blog tutorialAngular JS blog tutorial
Angular JS blog tutorial
 
#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
#31.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_스프링프레임워크 강좌, 재직자환급교육,실업자국비지원...
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and Performance
 
Using of TDD practices for Magento
Using of TDD practices for MagentoUsing of TDD practices for Magento
Using of TDD practices for Magento
 
Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4
 
Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of Django
 
Sane Async Patterns
Sane Async PatternsSane Async Patterns
Sane Async Patterns
 
Alfredo-PUMEX
Alfredo-PUMEXAlfredo-PUMEX
Alfredo-PUMEX
 
Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)
 
RicoLiveGrid
RicoLiveGridRicoLiveGrid
RicoLiveGrid
 
Django web framework
Django web frameworkDjango web framework
Django web framework
 
JavaScript
JavaScriptJavaScript
JavaScript
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4
 
WebGUI Developers Workshop
WebGUI Developers WorkshopWebGUI Developers Workshop
WebGUI Developers Workshop
 

Destaque

OSCON 2004: XML and Apache
OSCON 2004: XML and ApacheOSCON 2004: XML and Apache
OSCON 2004: XML and ApacheTed Leung
 
Rohit maitri dhrumil_namrata
Rohit maitri dhrumil_namrataRohit maitri dhrumil_namrata
Rohit maitri dhrumil_namrataDhruv Seth
 
Fort Mc Murray Hotel Group
Fort Mc Murray Hotel GroupFort Mc Murray Hotel Group
Fort Mc Murray Hotel Groupsaronyk
 
Ways to enhance your social media for nonprofits
Ways to enhance your social media for nonprofitsWays to enhance your social media for nonprofits
Ways to enhance your social media for nonprofitsSuna Gurol
 
Insurance 2 written
Insurance 2 writtenInsurance 2 written
Insurance 2 writtenFAROUQ
 
Developing secure software using Aspect oriented programming
Developing secure software using Aspect oriented programmingDeveloping secure software using Aspect oriented programming
Developing secure software using Aspect oriented programmingIOSR Journals
 

Destaque (6)

OSCON 2004: XML and Apache
OSCON 2004: XML and ApacheOSCON 2004: XML and Apache
OSCON 2004: XML and Apache
 
Rohit maitri dhrumil_namrata
Rohit maitri dhrumil_namrataRohit maitri dhrumil_namrata
Rohit maitri dhrumil_namrata
 
Fort Mc Murray Hotel Group
Fort Mc Murray Hotel GroupFort Mc Murray Hotel Group
Fort Mc Murray Hotel Group
 
Ways to enhance your social media for nonprofits
Ways to enhance your social media for nonprofitsWays to enhance your social media for nonprofits
Ways to enhance your social media for nonprofits
 
Insurance 2 written
Insurance 2 writtenInsurance 2 written
Insurance 2 written
 
Developing secure software using Aspect oriented programming
Developing secure software using Aspect oriented programmingDeveloping secure software using Aspect oriented programming
Developing secure software using Aspect oriented programming
 

Semelhante a TG2 Pluggable Apps: Using TurboGears2 Pluggable Apps

WordPress Structure and Best Practices
WordPress Structure and Best PracticesWordPress Structure and Best Practices
WordPress Structure and Best Practicesmarkparolisi
 
Introduction to backbone presentation
Introduction to backbone presentationIntroduction to backbone presentation
Introduction to backbone presentationBrian Hogg
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)Igor Bronovskyy
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexyananelson
 
Web applications with Catalyst
Web applications with CatalystWeb applications with Catalyst
Web applications with Catalystsvilen.ivanov
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Eric Palakovich Carr
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenerytoddbr
 
Modular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJSModular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJSGunnar Hillert
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2pyjonromero
 
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial EnEjb3 Struts Tutorial En
Ejb3 Struts Tutorial EnAnkur Dongre
 
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial EnEjb3 Struts Tutorial En
Ejb3 Struts Tutorial EnAnkur Dongre
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkBo-Yi Wu
 

Semelhante a TG2 Pluggable Apps: Using TurboGears2 Pluggable Apps (20)

WordPress Structure and Best Practices
WordPress Structure and Best PracticesWordPress Structure and Best Practices
WordPress Structure and Best Practices
 
Actionview
ActionviewActionview
Actionview
 
Django Vs Rails
Django Vs RailsDjango Vs Rails
Django Vs Rails
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Introduction to backbone presentation
Introduction to backbone presentationIntroduction to backbone presentation
Introduction to backbone presentation
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexy
 
Grails Advanced
Grails Advanced Grails Advanced
Grails Advanced
 
Web applications with Catalyst
Web applications with CatalystWeb applications with Catalyst
Web applications with Catalyst
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
Introduction to angular js
Introduction to angular jsIntroduction to angular js
Introduction to angular js
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
Modular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJSModular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJS
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2py
 
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial EnEjb3 Struts Tutorial En
Ejb3 Struts Tutorial En
 
Ejb3 Struts Tutorial En
Ejb3 Struts Tutorial EnEjb3 Struts Tutorial En
Ejb3 Struts Tutorial En
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 

Mais de Alessandro Molina

PyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdfPyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdfAlessandro Molina
 
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...Alessandro Molina
 
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For AssetsEP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For AssetsAlessandro Molina
 
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...Alessandro Molina
 
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATESPyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATESAlessandro Molina
 
PyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profitPyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profitAlessandro Molina
 
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrongPyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrongAlessandro Molina
 
PyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development UpdatedPyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development UpdatedAlessandro Molina
 
Reactive & Realtime Web Applications with TurboGears2
Reactive & Realtime Web Applications with TurboGears2Reactive & Realtime Web Applications with TurboGears2
Reactive & Realtime Web Applications with TurboGears2Alessandro Molina
 
Post-Mortem Debugging and Web Development
Post-Mortem Debugging and Web DevelopmentPost-Mortem Debugging and Web Development
Post-Mortem Debugging and Web DevelopmentAlessandro Molina
 
MongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profitMongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profitAlessandro Molina
 
PyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with MingPyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with MingAlessandro Molina
 
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...Alessandro Molina
 
EuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears TrainingEuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears TrainingAlessandro Molina
 
PyGrunn2013 High Performance Web Applications with TurboGears
PyGrunn2013  High Performance Web Applications with TurboGearsPyGrunn2013  High Performance Web Applications with TurboGears
PyGrunn2013 High Performance Web Applications with TurboGearsAlessandro Molina
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Alessandro Molina
 
From SQLAlchemy to Ming with TurboGears2
From SQLAlchemy to Ming with TurboGears2From SQLAlchemy to Ming with TurboGears2
From SQLAlchemy to Ming with TurboGears2Alessandro Molina
 

Mais de Alessandro Molina (17)

PyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdfPyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdf
 
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
 
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For AssetsEP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
 
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
 
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATESPyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
 
PyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profitPyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profit
 
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrongPyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
 
PyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development UpdatedPyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development Updated
 
Reactive & Realtime Web Applications with TurboGears2
Reactive & Realtime Web Applications with TurboGears2Reactive & Realtime Web Applications with TurboGears2
Reactive & Realtime Web Applications with TurboGears2
 
Post-Mortem Debugging and Web Development
Post-Mortem Debugging and Web DevelopmentPost-Mortem Debugging and Web Development
Post-Mortem Debugging and Web Development
 
MongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profitMongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profit
 
PyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with MingPyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with Ming
 
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
 
EuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears TrainingEuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears Training
 
PyGrunn2013 High Performance Web Applications with TurboGears
PyGrunn2013  High Performance Web Applications with TurboGearsPyGrunn2013  High Performance Web Applications with TurboGears
PyGrunn2013 High Performance Web Applications with TurboGears
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2
 
From SQLAlchemy to Ming with TurboGears2
From SQLAlchemy to Ming with TurboGears2From SQLAlchemy to Ming with TurboGears2
From SQLAlchemy to Ming with TurboGears2
 

Último

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
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
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 

Último (20)

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
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
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 

TG2 Pluggable Apps: Using TurboGears2 Pluggable Apps

  • 1. Pluggable Applications with TurboGears2 Using TurboGears2 pluggable applications Alessandro Molina @__amol__
  • 2. TurboGears2 ● Framework for rapid development encouraging customization ● Object Dispatch based, regular expressions can get messy, you will never have to write one anymore ● By default an XML template engine with error detection ● Declarative Models with transactional unit of work ● Built in Validation, Authentication, Authorization, Caching, Sessions, Migrations, MongoDB Support and many more.
  • 3. OverView CONTROLLER TEMPLATE class RootController(BaseController): <html xmlns="http://www.w3.org/1999/xhtml" error = ErrorController() xmlns:py="http://genshi.edgewall.org/" xmlns:xi="http://www.w3.org/2001/XInclude"> @expose('wiki20.templates.index') def index(self): <xi:include href="master.html" /> return dict(page='index') <head> <title>My Title</title> </head> MODEL <body> class Page(DeclarativeBase): <h1>${page}</h1> __tablename__ = 'pages' <div py:for="num in range(10)">${num}</div> </body> id = Column(Integer, primary_key=True) </html> pagename = Column(Text, unique=True) data = Column(Text)
  • 4. Object Dispatch URL CONTROLLER class BlogEntryController(BaseController): @expose() def index(self, post): return 'HI' /index RootController.index @expose() def edit(self, post): return 'HI' / RootController.index @expose() def update(self, post): return 'HI' /blog/3 BlogEntryController.index (post = 3) class RootController(BaseController): blog = BlogEntryController() /blog/update?post=3 BlogEntryController.update (post = 3) @expose() def index(self): return 'HI' /about RootController.about @expose() def about(self): /more/1/2/3 RootController.more return 'HI' (args[0]=1, args[1]=2, args[3]=3) @expose() def more(self, *args, **kw): /more?data=5 RootController.more return 'HI' (kw['data']=5)
  • 5. Declarative Model current_page = DBSession.query(Page).filter_by(pagename='index').first() pages = DBSession.query(Page).all() subpages = DBSession.query(Page).filter(Page.pagename.like('index_%')).all() TurboGears does this for us if DBSession.add(Page(pagename='index_about', no errors appeared during the data='About Content')) request. The Unit of Work will DBSession.flush() reorder insertions as required transaction.commit() by dependencies. TurboGears will automatically commit transactions on any session used inside the request if no error appears, otherwise a rollback is issued to avoid messing up the database.
  • 6. Genshi XML templating <!DOCTYPE html> ● Validated, if there is any error in the template <html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/"> structure it will be reported <head> <title>Geddit: News</title> ● XML based, just a bunch of attributes to your </head> <body class="index"> tags, this makes possible to edit the <div id="header"> templates with wysiwyg editors <h1>News</h1> </div> ● Conditional tags <ol py:if="links"> <li py:for="link in reversed(links)"> <a href="${link.url}">${link.title}</a> ● Tags content iteration posted by ${link.username} at ${link.time.strftime('%x %X')} </li> </ol> ● Variables substitution with escaping <p><a class="action" href="/submit/">Submit new link</a></p> ● Templates inheritance <div id="footer"> <hr /> <p class="legalese">© 2007 Edgewall Software</p> </div> </body> </html> Not so fast, if you want superfast templating TurboGears offers Mako support builtin. Mako is not validated and xml editors friendly but it is superfast.
  • 7. Quickstarting an Application $ virtualenv --no-site-packages -p python2.6 tg2env $ cd tg2env/ $ source bin/activate (tg2env)$ easy_install -i http://tg.gy/current tg.devtools (tg2env)$ paster quickstart example (tg2env)$ cd example/ (tg2env)$ python setup.py develop (tg2env)$ paster setup-app development.ini (tg2env)$ paster serve development.ini ● We use a virtual environment not to mess with our system wide packages ● Using TurboGears private index will permit to install the exact right version of the packages ● The quickstart command will create for us a new project with authentication, authorization and models. ● We use the setup.py develop command to install the project to be able to run it ● The setup-app command will initialize the database with a bunch of users for us, we can avoid this if we choose not to enable authentication ● Last we can call the serve command to run out application
  • 9. Sample Project ● Personal Website ● with Photo Galleries ● a Blog ● and many Wiki like pages
  • 10. Photo Galleries Install tgapp-photos pluggable (tg2env)$ easy_install tgapp-photos applications for photo albums support (tg2env)$ mkdir example/public/attachments from tgext.pluggable import plug We Plug tgapp-photos to have ready to plug(base_config, 'photos') use photo albums support <body> <div id="getting_started"> ${h.call_partial('photos.partials:albums')} Our Template ends being just a call to the partial that renders the previews of <div style="clear:both"/> our albums </div> </body> .photos_gallery { display: block; float: left; Some CSS to give a minimal look to our gallery text-align: center; margin-left: 10px; margin-bottom: 10px; }
  • 11. Our Photo galleries Argh, it look awful... But this is why CSS exist
  • 12. I want my blog, Now ! Install tgapp-smallpress for blogs (tg2env)$ easy_install tgapp-smallpress support and create a directory where it can store attachments from tgext.pluggable import plug We Plug tgapp-photos to have plug(base_config, 'photos') ready to use photo albums support <body> <div id="getting_started"> ${h.call_partial('photos.partials:albums')} Add call to smallpress partial to <div style="clear:both"/> render the list of articles of the ${h.call_partial('smallpress.partials:articles')} default blog </div> </body> #smallpress_articles { margin-top: 30px; } .smallpress_article h2 { margin-bottom: 0; } Our usual bunch of minimal styling. .smallpress_article h2 a { text-decoration: none; } .smallpress_article h4 { margin-top: 0; }
  • 14. What about the other pages? What's up with those About, Authentication, WSGI and Contact pages? We don't need them for our personal website! Let's remove all the methods in RootController between index and login and their templates!
  • 15. Doh! Well, actually we need to remove also the links inside the menu bar. Those are defined into master.html which is the master template that every page inherits.
  • 16. Let's now add wiki to our site First of all our model, it's just a page with a title and a content. from sqlalchemy import Table, ForeignKey, Column from sqlalchemy.types import Unicode, Integer, DateTime, Text from sqlalchemy.orm import relation, synonym from example.model import DeclarativeBase class WikiPage(DeclarativeBase): __tablename__ = 'wikipages' uid = Column(Integer, primary_key=True) pagename = Column(Text, unique=True) data = Column(Text)
  • 17. Let our pages exist First of all we need to make our WikiPage model available inside the model module: from example.model.wiki import WikiPage Then run setup-app again so that our new table get created. (tg2env)$ paster setup-app development.ini
  • 18. Time for some magic from tgext.crud import EasyCrudRestController class WikiController(EasyCrudRestController): model = model.WikiPage class RootController(BaseController): pages = WikiController(DBSession) [...]
  • 19. Works out of the box CRUD did all the work for us, now we just have to create our wiki pages!
  • 20. Fetch the pages for our menu _before method get called before calling every controller method and tmpl_context is the TurboGears template context, which is always available inside a request. from tg import tmpl_context class RootController(BaseController): pages = WikiController(DBSession) def _before(self, *args, **kw): tmpl_context.pages = DBSession.query(model.WikiPage).all()
  • 21. Let's draw our menu Inside master.html mainmenu add links for our pages <li py:for="page in getattr(tmpl_context, 'pages', [])"> <a href="${'/%s' % page.pagename}">${page.pagename}</a> </li>
  • 22. Doh! Again?! Well our website yet doesn't know how to display our wiki pages
  • 23. Serving our wiki pages from webob.exc import HTTPNotFound from webhelpers.markdown import Markdown class RootController(BaseController): pages = WikiController(DBSession) def _before(self, *args, **kw): _default method gets tmpl_context.pages = DBSession.query(model.WikiPage).all() executed every time Object Dispatch is able to resolve @expose('example.templates.index') the url only up to the def index(self): controller but is not able to return dict(page='index') find a method that matches the url @expose('example.templates.page') def _default(self, *args, **kw): page = None if args: page = DBSession.query(model.WikiPage).filter_by(pagename=args[0]).first() if not page: raise HTTPNotFound return dict(page=page.pagename, content=Markdown(page.data).convert())
  • 24. example.templates.page Very little to do, just show a title and its content. <html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include href="master.html" /> <head> <title>${page}</title> Markup is required to tell Genshi that the </head> value should not be escaped. <body> webhelpers.Markdown generated nice <h1>${page}</h1> HTML for us and we want to show the ${Markup(content)} rendering not the HTML itself! </body> </html>
  • 25. Woh! It works! Our website is ready! Now we can add any number of pages using the Markdown syntax.
  • 26. Have Fun! TurboGears2, its crud and pluggable applications can make as easy as 1,2,3 creating a web application, just open your editor and have fun! http://www.turbogears.org