Changes between Version 35 and Version 36 of TracDev/PortingFromGenshiToJinja
- Timestamp:
- Jan 15, 2017, 1:00:11 AM (7 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
TracDev/PortingFromGenshiToJinja
v35 v36 3 3 4 4 The following documentation corresponds to the [Proposals/Jinja Jinja] development proposal; it will be in Trac 1.3.x if all goes well \\ 5 (Git branch: [log:cboos.git@jinja2] - [https://github.com/cboos/trac.git github mirror]).5 (Git branch: [log:cboos.git@jinja2] (original) - [log:cboos.git@jinja2-trunk-r15341] (latest) - [https://github.com/cboos/trac.git github mirror]). 6 6 7 7 Track the integration progress in #12639. … … 14 14 15 15 For migrating your own templates, a good way to start is to learn from examples. 16 Compare the 'j...' Jinja templates found in source:cboos.git/trac/templates@jinja2 with their corresponding Genshi ones.16 Compare the [source:cboos.git/trac/templates@jinja2-trunk-r15341 Jinja2 trac/templates] with their [source:trunk/trac/templates Genshi counterpart]. 17 17 18 18 In the first part of this document, we try to cover all the Genshi features used by Trac and present their Jinja2 equivalent. Whenever possible, we tried to minimize these differences by customizing the Jinja2 syntax. For example, we use `${...}` for variable expansion, like Genshi does, instead of `{{...}}`. Another aspect of our usage convention is that we favor [#ifthenelse line statements] over `{% ... %}`. So even someone familiar with the "default" Jinja2 syntax should glance through this document to see how "we" use Jinja2, as summarized in the table below. … … 20 20 The last part of the document describes the Python code changes, focusing notably on how to replace the deprecated `ITemplateStreamFilter` interface. 21 21 22 Note that Genshi will be supported concurrently with Jinja2 only for a short while, including the deprecated `ITemplateStreamFilter` interface, but probably only during the 1.3.x development period, and at most for the 1.4-stable period. If for some reason you're stuck to having to support Genshi templates, you'll have to stick to Trac 1.2.x or 1.3.x. But you really should make the transition effort as Jinja2 templates are 5-10x faster than their Genshi equivalent, for only a 1/5th of the cost in memory usage. 22 Note that Genshi will be supported concurrently with Jinja2 only for a short while, for the 1.3.x development period and for the 1.4-stable period. If for some reason you're stuck to having to support Genshi templates, you'll have to stick to Trac 1.2.x or 1.3.x. But you really should make the transition effort as Jinja2 templates are 5-10x faster than their Genshi equivalent, for only a 1/5th of the cost in memory usage. 23 23 24 24 25 == The Jinja2 syntax … … 56 57 || lstrip_blocks || yes || whitespace removal before a block 57 58 || newstyle_gettext || yes || i.e. like the Trac `gettext` 59 58 60 59 61 == Changes in the HTML … … 143 145 # set can_append = false 144 146 # set preview_mode = false 145 # include " jticket_box.html"147 # include "ticket_box.html" 146 148 # endwith 147 149 }}} … … 492 494 </html> 493 495 }}} 494 - Jinja [source:cboos.git/trac/templates/ jindex.html@jinja2 jindex.html]:496 - Jinja [source:cboos.git/trac/templates/index.html@jinja2-trunk-r15341 index.html]: 495 497 {{{#!html+jinja 496 498 <!DOCTYPE html> … … 521 523 In this small example, there's no common Trac layout used (as the index is a bit special). 522 524 For how a "normal" template looks like, see for example 523 [source:trac/templates/ jdiff_form.html@jinja2 jdiff_form.html], another small template.525 [source:trac/templates/diff_form.html@jinja2-trunk-r15341 diff_form.html], another small template. 524 526 525 527 Note that a Jinja2 .html template can usually be rendered directly in the browser, to have a rough taste of how it will look like: … … 555 557 Instead of the Genshi way of including a template containing filters, the Jinja2 way follows an "object oriented" approach, with inheritance and overriders. Consider that some named sections (or "blocks") of the base template are similar to "methods", imagine that you only have to "subclass" this base template and "reimplement" the overridable methods with your specific content, and there you have it. 556 558 557 More specifically, you'll have to "extend" the [source:cboos.git/trac/templates/ jlayout.html@jinja2 jlayout.html] template, and redefine the "head", and "content" blocks if needed.558 559 All the details are available in HtmlTemplates#Jinja architecture, including a walkthrough for the specific example of the [source:cboos.git/trac/search/templates/jsearch.html@jinja2 jsearch.html] template.560 561 For the jsearch.html example we focus on the //structure// of the templates, the //include// relationship and the decomposition in //blocks//.562 563 564 But we also have a complete conversion [./Example example], which displays the Genshi wiki_view.html template and the Jinja2 jwiki_view.html template side-by-side, along with comments explaining the conversion choices.559 More specifically, you'll have to "extend" the [source:cboos.git/trac/templates/layout.html@jinja2-trunk-r15341 layout.html] template, and redefine the "head", and "content" blocks if needed. 560 561 All the details are available in HtmlTemplates#Jinja2architecture, including a walkthrough for the specific example of the [source:cboos.git/trac/search/templates/search.html@jinja2-trunk-r15341 search.html] template. 562 563 For the search.html example we focus on the //structure// of the templates, the //include// relationship and the decomposition in //blocks//. 564 565 566 But we also have a complete conversion [./Example example], which displays the Genshi wiki_view.html template and the Jinja2 wiki_view.html template side-by-side, along with comments explaining the conversion choices. 565 567 566 568 === Tips and tricks … … 576 578 at the same time as the template name. This hasn't changed with Jinja2. 577 579 578 In fact, no changes to the `IRequestHandler` interface were needed. 580 The `IRequestHandler.process_request` method has seen one, important, change: instead of returning a triple of the template, data, and content type, a simple pair of template and data must be returned. 581 582 If the legacy return convention is used, this means that `'template.html'` is supposed to be a Genshi template: 583 {{{#!py 584 return 'template.html', data, None 585 }}} 586 (`None` here is interpreted to mean the default content type, i.e. `'text/html'`) 587 588 The new return convention is simpler, and means that `'template.html'` is now supposed to be a Jinja2 template: 589 {{{#!py 590 return 'template.html', data 591 }}} 592 593 If a special content-type must be used, or if other variation on the generation of the content must be specified, this can now be done by passing a `dict`: 594 {{{#!py 595 return 'template.html', data, {'content_type': 'application/rss+xml'} 596 }}} 597 This has the advantage of supporting a few more keywords (see the API doc), and to be extensible with more metadata at little cost. 598 599 Note that as long as we have to support the legacy Genshi templates, a `None` value passed as third argument won't be interpreted as an empty `dict`, but rather as an empty `content_type`. 579 600 580 601 … … 589 610 There were two post-processing steps from which plugin writers did benefit, possibly unknowingly: 590 611 1. the addition of the `__FORM_TOKEN` hidden parameter to <form> elements, necessary for successful POST operations 591 2. accessibility key enabling/disabling (TODO)612 2. accessibility key enabling/disabling 592 613 593 614 As this no longer happen, it's now the responsibility of plugin writers to add this <input> in their content. This is simple enough: … … 598 619 </form> 599 620 }}} 621 600 622 This gets even simpler thanks to a default macro: 601 623 {{{#!html+jinja … … 606 628 }}} 607 629 608 The `jmacros` corresponds to the [source:cboos.git/trac/templates/jmacros.html@jinja2 trac/templates/jmacros.html] default macros, and this file is included by default (in `jlayout.html`), so you don't have to bother to include it yourself (as most of the templates will extend `jlayout.html`). 609 630 The `jmacros` in the above corresponds to the [source:cboos.git/trac/templates/macros.html@jinja2-trunk-r15341 trac/templates/macros.html] default macros, and this file is included by default (in `layout.html`), so you don't have to bother to include it yourself, as long as your template extends `layout.html`. 631 632 For the accessibility key, it's also quite simple: instead of hard-coding the key as an `accesskey="e"` attribute, simply use the `accesskey('e')` function call, it will know if it has to produce the attribute or not depending on the current user preferences. 610 633 611 634 ==== Hooking into the HTML content produced by other templates … … 615 638 So this means this specific step of the migration, perhaps the less straightforward, will be of interest for most plugin developers. 616 639 617 Note that though it wouldn't harm to leave the code for `ITemplateStreamFilter` around for use by Trac < 1.4, the new suggested way also works great with earlier versions of Trac (1.0 and 1.2, perhaps even 0.12), so there's really no reason to maintain both versions once you did the switch. 640 Note that though we guarantee some level of support for the `ITemplateStreamFilter` during the transition period, the new suggested way also works great with earlier versions of Trac (1.0 and 1.2, perhaps even 0.12), so there's really no reason to maintain both versions once you did the switch. 641 642 One strong incentive for dropping the `ITemplateStreamFilter` usage in your code is that by not doing so you basically **kill all the performance benefits** of the switch to Jinja2. The support of `ITemplateStreamFilter` implies that we first render the page to HTML using Jinja2, then parse it back as an HTML stream and feed this stream to the Genshi filter, so that it can be transformed, and then finally rendered again(!). 618 643 619 644 The steps for replacing `filter_stream()` are the following: … … 805 830 req, 'query_results.html', data, None, fragment=True) 806 831 }}} 807 //implementing [source:cboos.git/trac/ticket/query.py@jinja2 #L1403Ticket Query] macro (''table'' mode)//832 //implementing [source:cboos.git/trac/ticket/query.py@jinja2-trunk-r15341#L1425 Ticket Query] macro (''table'' mode)// 808 833 809 834 A newer alternative is to use `Chrome.generate_template_fragment`, as in: