Pluggable Applications with      TurboGears2  Using TurboGears2 pluggable applications                 Alessandro Molina  ...
TurboGears2● Framework for rapid development encouraging  customization● Object Dispatch based, regular expressions can ge...
OverViewCONTROLLER                                 TEMPLATEclass RootController(BaseController):      <html xmlns="http://...
Object Dispatch                                                       URL                     CONTROLLERclass BlogEntryCon...
Declarative Modelcurrent_page = DBSession.query(Page).filter_by(pagename=index).first()pages = DBSession.query(Page).all()...
Genshi XML templating<!DOCTYPE html>                                                     ●    Validated, if there is any e...
Quickstarting an Application                $ virtualenv --no-site-packages -p python2.6 tg2env                $ cd tg2env...
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...
Our Photo galleries        Argh, it look awful...       But this is why CSS exist
I want my blog, Now !                                                         Install tgapp-smallpress for blogs(tg2env)$ ...
Well, somehow it works
What about the other pages?Whats up with those About, Authentication,WSGI and Contact pages? We dont need themfor our pers...
Doh!Well, actually we need to remove also the linksinside the menu bar. Those are defined intomaster.html which is the mas...
Lets now add wiki to our siteFirst of all our model, its just a page with a titleand a content.from sqlalchemy import Tabl...
Let our pages existFirst of all we need to make our WikiPagemodel available inside the model module:from example.model.wik...
Time for some magicfrom tgext.crud import EasyCrudRestControllerclass WikiController(EasyCrudRestController):  model = mod...
Works out of the boxCRUD did all the work for us, now we just haveto create our wiki pages!
Fetch the pages for our menu_before method get called before calling everycontroller method and tmpl_context is theTurboGe...
Lets draw our menuInside master.html mainmenu add links forour pages<li py:for="page in getattr(tmpl_context, pages, [])">...
Doh!Again?!Well our website yet doesnt know how todisplay our wiki pages
Serving our wiki pagesfrom webob.exc import HTTPNotFoundfrom webhelpers.markdown import Markdownclass RootController(BaseC...
example.templates.pageVery little to do, just show a title and itscontent.<html xmlns="http://www.w3.org/1999/xhtml"      ...
Woh! It works!Our website is ready! Now we can add anynumber of pages using the Markdown syntax.
Have Fun!TurboGears2, its crud and pluggableapplications can make as easy as 1,2,3 creatinga web application, just open yo...
Upcoming SlideShare
Loading in …5
×

TurboGears2 Pluggable Applications

3,123 views
3,059 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,123
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
7
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

TurboGears2 Pluggable Applications

  1. 1. Pluggable Applications with TurboGears2 Using TurboGears2 pluggable applications Alessandro Molina @__amol__
  2. 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. 3. OverViewCONTROLLER TEMPLATEclass 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. 4. Object Dispatch URL CONTROLLERclass 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. 5. Declarative Modelcurrent_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 errorappears, otherwise a rollback is issued to avoid messing up the database.
  6. 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. 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
  8. 8. Explore Quickstart
  9. 9. Sample Project● Personal Website● with Photo Galleries● a Blog● and many Wiki like pages
  10. 10. Photo Galleries Install tgapp-photos pluggable(tg2env)$ easy_install tgapp-photos applications for photo albums support(tg2env)$ mkdir example/public/attachmentsfrom tgext.pluggable import plug We Plug tgapp-photos to have ready toplug(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. 11. Our Photo galleries Argh, it look awful... But this is why CSS exist
  12. 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 attachmentsfrom tgext.pluggable import plug We Plug tgapp-photos to haveplug(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; }
  13. 13. Well, somehow it works
  14. 14. What about the other pages?Whats up with those About, Authentication,WSGI and Contact pages? We dont need themfor our personal website!Lets remove all the methods inRootController between index and loginand their templates!
  15. 15. Doh!Well, actually we need to remove also the linksinside the menu bar. Those are defined intomaster.html which is the master templatethat every page inherits.
  16. 16. Lets now add wiki to our siteFirst of all our model, its just a page with a titleand a content.from sqlalchemy import Table, ForeignKey, Columnfrom sqlalchemy.types import Unicode, Integer, DateTime, Textfrom sqlalchemy.orm import relation, synonymfrom example.model import DeclarativeBaseclass WikiPage(DeclarativeBase): __tablename__ = wikipages uid = Column(Integer, primary_key=True) pagename = Column(Text, unique=True) data = Column(Text)
  17. 17. Let our pages existFirst of all we need to make our WikiPagemodel available inside the model module:from example.model.wiki import WikiPageThen run setup-app again so that our newtable get created.(tg2env)$ paster setup-app development.ini
  18. 18. Time for some magicfrom tgext.crud import EasyCrudRestControllerclass WikiController(EasyCrudRestController): model = model.WikiPageclass RootController(BaseController): pages = WikiController(DBSession) [...]
  19. 19. Works out of the boxCRUD did all the work for us, now we just haveto create our wiki pages!
  20. 20. Fetch the pages for our menu_before method get called before calling everycontroller method and tmpl_context is theTurboGears template context, which is alwaysavailable inside a request.from tg import tmpl_contextclass RootController(BaseController): pages = WikiController(DBSession) def _before(self, *args, **kw): tmpl_context.pages = DBSession.query(model.WikiPage).all()
  21. 21. Lets draw our menuInside master.html mainmenu add links forour pages<li py:for="page in getattr(tmpl_context, pages, [])"> <a href="${/%s % page.pagename}">${page.pagename}</a></li>
  22. 22. Doh!Again?!Well our website yet doesnt know how todisplay our wiki pages
  23. 23. Serving our wiki pagesfrom webob.exc import HTTPNotFoundfrom webhelpers.markdown import Markdownclass 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. 24. example.templates.pageVery little to do, just show a title and itscontent.<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. 25. Woh! It works!Our website is ready! Now we can add anynumber of pages using the Markdown syntax.
  26. 26. Have Fun!TurboGears2, its crud and pluggableapplications can make as easy as 1,2,3 creatinga web application, just open your editor andhave fun! http://www.turbogears.org

×