SlideShare a Scribd company logo
KAJIKI
THE FAST AND VALIDATED TEMPLATE
ENGINE YOU WERE LOOKING FOR
Alessandro Molina
@__amol__
amol@turbogears.org
Who am I
● Passionate Python Developer
● TurboGears2 core team member
● Beaker caching/session framework
current maintainer
● Author of DukPy js env for Python and
DEPOT file storage framework
● Contributor to Ming, ToscaWidgets2,
Formencode, WebOb, Kajiki, ...
Why?
● There are tens of template engines out
there, but people often only know the
default one of their web framework.
● Different template engines can differ in
important features, not just syntax.
● Working on one has been fun and
interesting.
Template Engines
TYPE NAME URL
Markup + Streamed Genshi http://genshi.edgewall.org/
Text + Compiled Mako http://www.makotemplates.org/
Text + Compiled Jinja http://jinja.pocoo.org/
Markup + Compiled Kajiki http://kajiki.readthedocs.io/
One more Template Engine?
● We loved the fact that Genshi templates
could by opened with any HTML editor
● We loved Genshi syntax, concise and
reflecting the output itself.
● We loved Genshi so much TG2.2 included
it in all projects, to make it available for
pluggable apps and extensions.
Right Timing...
How I felt...
Well...
● Genshi was pretty complex. We didn’t
want to maintain such complexity.
● Streaming was powerful but hard to use,
very few people understood genshi
inheritance. And it was really slow.
● A TG team member was experimenting
with the idea of a similar engine.
Kajiki
<html>
<head>
<title py:content="title">This is replaced.</title>
</head>
<body>
<p>These are some fruits:</p>
<ul>
<li py:for="fruit in fruits">
I like ${fruit}s
</li>
</ul>
</body>
</html>
Directives
● py:if & py:else
● py:switch & py:case & py:else
● py:for
● py:def
● py:strip
● py:with
● py:attrs
● py:block & py:extends
● ...
How It Works
● Your template is parsed and converted to
Python code.
● Whenever the template is rendered the
generated python code is executed.
● The python code is yielded by a generator
that resembles the DOM of the document.
Architecture
PARSER
COMPILER
INTERMEDIATE
REPRESENTATION
PYTHON
READ XML AND GENERATE DOM OUT OF IT
WITH SAX
NAVIGATE DOM AND CREATE IR FOR ITS
NODES
ITERATE THE IR NODES TO GENERATE
PYTHON CODE
RUN PYTHON CODE TO RENDER TEMPLATE
Compiled Kajiki
class template:
@kajiki.expose
def __main__():
yield u'<html>n <head>n <title>'
yield self.__kj__.escape(title)
yield u'</title>n </head>n <body>n <p>'
yield local.__kj__.gettext(u'These are some fruits:')
yield u'</p>n <ul>n '
for fruit in fruits:
yield u'<li>'
yield local.__kj__.gettext(u'n I like ')
yield self.__kj__.escape(fruit)
yield local.__kj__.gettext(u'sn ')
yield u'</li>'
yield u'n </ul>n </body>n</html>'
Rendered Kajiki
<html>
<head>
<title>A Kajiki Template</title>
</head>
<body>
<p>These are some fruits:</p>
<ul>
<li>
I like oranges
</li><li>
I like apples
</li>
</ul>
</body>
</html>
That makes it pretty Fast
● Mako
○ Rendered 1M mako templates in 22.217651844
● Kajiki
○ Rendered 1M Kajiki templates in 11.8710489273
%for user in users:
<span>Hello {{ user }}!</span>
%endfor
<span py:for="user in users">
Hello ${user}!
</span>
It’s really just python!
Mad science included!
import kajiki
loader = kajiki.FileLoader('.', force_mode='xml')
tmpl = loader.load('mypage.kajiki')
with open('cython_test.pyx', 'wb') as pyx:
py_text = tmpl.py_text.replace('@kajiki.expose', '@staticmethod')
py_text = py_text.replace('__main__():', '__main__(self, local, users):')
py_text = py_text.replace('template = kajiki.Template(template)', '')
pyx.write(py_text)
import pyximport; pyximport.install()
import cython_test
class template:
@kajiki.expose
def __main__():
return cytmpl.__main__(self, local, users)
template = kajiki.Template(template)
print template(dict(cytmpl=cython_test.template, users=range(100000))).render()
Don’t try this at home
● Huge hack, but theoretically it can work.
With minor tweaks Kajiki itself could
generate cython compatible code.
● Rendering python 11.86215686798
● Rederning cython 9.07893800735
But being Python is easy to debug
Integrates with Python debuggers
Python Syntax Checking
kajiki.template.KajikiSyntaxError: [<string>:9]
invalid syntax
yield local.__kj__.gettext(u'These are some of
my favorite fruits:')
yield u'</p>n <ul>n '
--> for fruit on fuits:
yield u'<li>'
yield local.__kj__.gettext(u'n I like ')
Validated Templates
● As Kajiki understands the document you
are writing (it’s not just text) it can take
steps specific to HTML generation:
○ Error Reporting
○ Escaping
○ Automatic i18n
○ Minification
Malformed HTML Detection
kajiki.xml_template.XMLTemplateParseError:
[./plain.kajiki:10] mismatched tag
<li py:for="fruit in fruits">
I like ${fruit}s
--> </span>
</ul>
</body>
Escaping handled for us
<li py:for="fruit in fruits">
I like ${fruit}s
</li>
template(dict(
fruits=['<apple>'],
title='A Kajiki Template'
)).render()
<li>
I like &lt;apple&gt;s
</li>
Easy Translations
<li py:for="fruit in fruits">
I like ${fruit}s
</li>
for fruit on fuits:
yield u'<li>'
yield local.__kj__.gettext(u'n I like ')
Minification
tmpl = loader.load('plain.kajiki', strip_text=False)
<ul>
<li>
I like oranges
</li><li>
I like apple
</li><li>
I like kiwis
</li>
</ul>
tmpl = loader.load('plain.kajiki', strip_text=True)
<ul><li>I like oranges</li><li>I like apple</li><li>I like
kiwis</li></ul>
Text engine available too
>>> Template = kajiki.TextTemplate('''
... {%if foo %}
... bar
... {%else%}
... baz
... {%end%}
... ''')
>>> print(Template(dict(foo=True)).render())
bar
>>> print(Template(dict(foo=False)).render())
baz
Feel free to try it!
● Python 2.6, 2.7, 3.2, 3.3, 3.4 and 3.5
● pip install kajiki
● Come and try it!
https://github.com/nandoflorestan/kajiki
● Still young! Feel free to open issues, send
pull requests, suggest features!
Questions?

More Related Content

What's hot

A million connections and beyond - Node.js at scale
A million connections and beyond - Node.js at scaleA million connections and beyond - Node.js at scale
A million connections and beyond - Node.js at scale
Tom Croucher
 
Node js presentation
Node js presentationNode js presentation
Node js presentation
martincabrera
 
Building servers with Node.js
Building servers with Node.jsBuilding servers with Node.js
Building servers with Node.js
ConFoo
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
Tom Croucher
 

What's hot (20)

Node Architecture and Getting Started with Express
Node Architecture and Getting Started with ExpressNode Architecture and Getting Started with Express
Node Architecture and Getting Started with Express
 
RDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по DipRDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по Dip
 
How to Write Node.js Module
How to Write Node.js ModuleHow to Write Node.js Module
How to Write Node.js Module
 
Non-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.jsNon-blocking I/O, Event loops and node.js
Non-blocking I/O, Event loops and node.js
 
NodeJS for Beginner
NodeJS for BeginnerNodeJS for Beginner
NodeJS for Beginner
 
Understanding the Node.js Platform
Understanding the Node.js PlatformUnderstanding the Node.js Platform
Understanding the Node.js Platform
 
NodeJS
NodeJSNodeJS
NodeJS
 
A million connections and beyond - Node.js at scale
A million connections and beyond - Node.js at scaleA million connections and beyond - Node.js at scale
A million connections and beyond - Node.js at scale
 
Node js presentation
Node js presentationNode js presentation
Node js presentation
 
Building a real life application in node js
Building a real life application in node jsBuilding a real life application in node js
Building a real life application in node js
 
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
 
Building servers with Node.js
Building servers with Node.jsBuilding servers with Node.js
Building servers with Node.js
 
node.js: Javascript's in your backend
node.js: Javascript's in your backendnode.js: Javascript's in your backend
node.js: Javascript's in your backend
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
RESTful API In Node Js using Express
RESTful API In Node Js using Express RESTful API In Node Js using Express
RESTful API In Node Js using Express
 
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
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.js
 
Angular 1 + es6
Angular 1 + es6Angular 1 + es6
Angular 1 + es6
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
 
Nodejs intro
Nodejs introNodejs intro
Nodejs intro
 

Similar to PyconIE 2016 - Kajiki, the fast and validated template engine your were looking for

[GEMINI EXTERNAL DECK] Introduction to Gemini.pptx
[GEMINI EXTERNAL DECK] Introduction to Gemini.pptx[GEMINI EXTERNAL DECK] Introduction to Gemini.pptx
[GEMINI EXTERNAL DECK] Introduction to Gemini.pptx
AhmedElbaloug
 

Similar to PyconIE 2016 - Kajiki, the fast and validated template engine your were looking for (20)

2016 stop writing javascript frameworks by Joe Gregorio
2016 stop writing javascript frameworks by Joe Gregorio2016 stop writing javascript frameworks by Joe Gregorio
2016 stop writing javascript frameworks by Joe Gregorio
 
Dust.js
Dust.jsDust.js
Dust.js
 
Creando microservicios con java micro profile y tomee - CUNORI 2020
Creando microservicios con java micro profile y tomee - CUNORI 2020Creando microservicios con java micro profile y tomee - CUNORI 2020
Creando microservicios con java micro profile y tomee - CUNORI 2020
 
EuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears TrainingEuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears Training
 
Yii2 by Peter Jack Kambey
Yii2 by Peter Jack KambeyYii2 by Peter Jack Kambey
Yii2 by Peter Jack Kambey
 
Revealing ALLSTOCKER
Revealing ALLSTOCKERRevealing ALLSTOCKER
Revealing ALLSTOCKER
 
Django by rj
Django by rjDjango by rj
Django by rj
 
Second Skin: Real-Time Retheming a Legacy Web Application with Diazo in the C...
Second Skin: Real-Time Retheming a Legacy Web Application with Diazo in the C...Second Skin: Real-Time Retheming a Legacy Web Application with Diazo in the C...
Second Skin: Real-Time Retheming a Legacy Web Application with Diazo in the C...
 
Drupal 8 introduction to theming
Drupal 8  introduction to themingDrupal 8  introduction to theming
Drupal 8 introduction to theming
 
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
 
Extending CMS Made Simple
Extending CMS Made SimpleExtending CMS Made Simple
Extending CMS Made Simple
 
HTML literals, the JSX of the platform
HTML literals, the JSX of the platformHTML literals, the JSX of the platform
HTML literals, the JSX of the platform
 
Let’s template
Let’s templateLet’s template
Let’s template
 
[GEMINI EXTERNAL DECK] Introduction to Gemini.pptx
[GEMINI EXTERNAL DECK] Introduction to Gemini.pptx[GEMINI EXTERNAL DECK] Introduction to Gemini.pptx
[GEMINI EXTERNAL DECK] Introduction to Gemini.pptx
 
Turbogears2 tutorial to create mvc app
Turbogears2 tutorial to create mvc appTurbogears2 tutorial to create mvc app
Turbogears2 tutorial to create mvc app
 
Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.
Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.
Taming the Legacy Beast: Turning wild old code into a sleak new thoroughbread.
 
Company Visitor Management System Report.docx
Company Visitor Management System Report.docxCompany Visitor Management System Report.docx
Company Visitor Management System Report.docx
 
Introduce Django
Introduce DjangoIntroduce Django
Introduce Django
 
Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...
Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...
Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...
 
IDE and Toolset For Magento Development
IDE and Toolset For Magento DevelopmentIDE and Toolset For Magento Development
IDE and Toolset For Magento Development
 

More from Alessandro 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 profit
Alessandro Molina
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2
Alessandro Molina
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
Alessandro Molina
 

More from Alessandro Molina (13)

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
 
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
 
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...
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
 

Recently uploaded

Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 

Recently uploaded (20)

GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
ODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User Group
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
КАТЕРИНА АБЗЯТОВА «Ефективне планування тестування ключові аспекти та практ...
КАТЕРИНА АБЗЯТОВА  «Ефективне планування тестування  ключові аспекти та практ...КАТЕРИНА АБЗЯТОВА  «Ефективне планування тестування  ключові аспекти та практ...
КАТЕРИНА АБЗЯТОВА «Ефективне планування тестування ключові аспекти та практ...
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilot™
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 

PyconIE 2016 - Kajiki, the fast and validated template engine your were looking for

  • 1. KAJIKI THE FAST AND VALIDATED TEMPLATE ENGINE YOU WERE LOOKING FOR Alessandro Molina @__amol__ amol@turbogears.org
  • 2. Who am I ● Passionate Python Developer ● TurboGears2 core team member ● Beaker caching/session framework current maintainer ● Author of DukPy js env for Python and DEPOT file storage framework ● Contributor to Ming, ToscaWidgets2, Formencode, WebOb, Kajiki, ...
  • 3. Why? ● There are tens of template engines out there, but people often only know the default one of their web framework. ● Different template engines can differ in important features, not just syntax. ● Working on one has been fun and interesting.
  • 4. Template Engines TYPE NAME URL Markup + Streamed Genshi http://genshi.edgewall.org/ Text + Compiled Mako http://www.makotemplates.org/ Text + Compiled Jinja http://jinja.pocoo.org/ Markup + Compiled Kajiki http://kajiki.readthedocs.io/
  • 5. One more Template Engine? ● We loved the fact that Genshi templates could by opened with any HTML editor ● We loved Genshi syntax, concise and reflecting the output itself. ● We loved Genshi so much TG2.2 included it in all projects, to make it available for pluggable apps and extensions.
  • 8. Well... ● Genshi was pretty complex. We didn’t want to maintain such complexity. ● Streaming was powerful but hard to use, very few people understood genshi inheritance. And it was really slow. ● A TG team member was experimenting with the idea of a similar engine.
  • 9. Kajiki <html> <head> <title py:content="title">This is replaced.</title> </head> <body> <p>These are some fruits:</p> <ul> <li py:for="fruit in fruits"> I like ${fruit}s </li> </ul> </body> </html>
  • 10. Directives ● py:if & py:else ● py:switch & py:case & py:else ● py:for ● py:def ● py:strip ● py:with ● py:attrs ● py:block & py:extends ● ...
  • 11. How It Works ● Your template is parsed and converted to Python code. ● Whenever the template is rendered the generated python code is executed. ● The python code is yielded by a generator that resembles the DOM of the document.
  • 12. Architecture PARSER COMPILER INTERMEDIATE REPRESENTATION PYTHON READ XML AND GENERATE DOM OUT OF IT WITH SAX NAVIGATE DOM AND CREATE IR FOR ITS NODES ITERATE THE IR NODES TO GENERATE PYTHON CODE RUN PYTHON CODE TO RENDER TEMPLATE
  • 13. Compiled Kajiki class template: @kajiki.expose def __main__(): yield u'<html>n <head>n <title>' yield self.__kj__.escape(title) yield u'</title>n </head>n <body>n <p>' yield local.__kj__.gettext(u'These are some fruits:') yield u'</p>n <ul>n ' for fruit in fruits: yield u'<li>' yield local.__kj__.gettext(u'n I like ') yield self.__kj__.escape(fruit) yield local.__kj__.gettext(u'sn ') yield u'</li>' yield u'n </ul>n </body>n</html>'
  • 14. Rendered Kajiki <html> <head> <title>A Kajiki Template</title> </head> <body> <p>These are some fruits:</p> <ul> <li> I like oranges </li><li> I like apples </li> </ul> </body> </html>
  • 15. That makes it pretty Fast ● Mako ○ Rendered 1M mako templates in 22.217651844 ● Kajiki ○ Rendered 1M Kajiki templates in 11.8710489273 %for user in users: <span>Hello {{ user }}!</span> %endfor <span py:for="user in users"> Hello ${user}! </span>
  • 16. It’s really just python! Mad science included! import kajiki loader = kajiki.FileLoader('.', force_mode='xml') tmpl = loader.load('mypage.kajiki') with open('cython_test.pyx', 'wb') as pyx: py_text = tmpl.py_text.replace('@kajiki.expose', '@staticmethod') py_text = py_text.replace('__main__():', '__main__(self, local, users):') py_text = py_text.replace('template = kajiki.Template(template)', '') pyx.write(py_text) import pyximport; pyximport.install() import cython_test class template: @kajiki.expose def __main__(): return cytmpl.__main__(self, local, users) template = kajiki.Template(template) print template(dict(cytmpl=cython_test.template, users=range(100000))).render()
  • 17. Don’t try this at home ● Huge hack, but theoretically it can work. With minor tweaks Kajiki itself could generate cython compatible code. ● Rendering python 11.86215686798 ● Rederning cython 9.07893800735
  • 18. But being Python is easy to debug
  • 20. Python Syntax Checking kajiki.template.KajikiSyntaxError: [<string>:9] invalid syntax yield local.__kj__.gettext(u'These are some of my favorite fruits:') yield u'</p>n <ul>n ' --> for fruit on fuits: yield u'<li>' yield local.__kj__.gettext(u'n I like ')
  • 21. Validated Templates ● As Kajiki understands the document you are writing (it’s not just text) it can take steps specific to HTML generation: ○ Error Reporting ○ Escaping ○ Automatic i18n ○ Minification
  • 22. Malformed HTML Detection kajiki.xml_template.XMLTemplateParseError: [./plain.kajiki:10] mismatched tag <li py:for="fruit in fruits"> I like ${fruit}s --> </span> </ul> </body>
  • 23. Escaping handled for us <li py:for="fruit in fruits"> I like ${fruit}s </li> template(dict( fruits=['<apple>'], title='A Kajiki Template' )).render() <li> I like &lt;apple&gt;s </li>
  • 24. Easy Translations <li py:for="fruit in fruits"> I like ${fruit}s </li> for fruit on fuits: yield u'<li>' yield local.__kj__.gettext(u'n I like ')
  • 25. Minification tmpl = loader.load('plain.kajiki', strip_text=False) <ul> <li> I like oranges </li><li> I like apple </li><li> I like kiwis </li> </ul> tmpl = loader.load('plain.kajiki', strip_text=True) <ul><li>I like oranges</li><li>I like apple</li><li>I like kiwis</li></ul>
  • 26. Text engine available too >>> Template = kajiki.TextTemplate(''' ... {%if foo %} ... bar ... {%else%} ... baz ... {%end%} ... ''') >>> print(Template(dict(foo=True)).render()) bar >>> print(Template(dict(foo=False)).render()) baz
  • 27. Feel free to try it! ● Python 2.6, 2.7, 3.2, 3.3, 3.4 and 3.5 ● pip install kajiki ● Come and try it! https://github.com/nandoflorestan/kajiki ● Still young! Feel free to open issues, send pull requests, suggest features!