Odoo Help


This community is for beginners and experts willing to share their Odoo knowledge. It's not a forum to discuss ideas, but a knowledge base of questions and their answers.


How to use SimpleTAL instead of QWeb in OERP7?

on 3/27/13, 10:54 AM 1,583 views

From the /developers/web/module/ section of the docs:

OpenERP Web’s template language is QWeb. Although any templating engine can be used (e.g. mustache or _.template)

This is great but it does not give any details on how to replace Qweb with another templating engine. I am interested in using SimpleTAL instead of QWeb, does anybody have any pointers/advice on how to go about doing this?

On 3/29/13, 10:43 AM

Here's what I have tried so far and it works. Go to addons/web/controllers/testing.py and replace TestRunnerController with following (back-up original 1st):

class TestRunnerController(http.Controller):
_cp_path = '/web/tests'

def index(self, req, mod=None, **kwargs):

    input = open('<PATH>/taltest.tal', 'r')
    template = simpleTAL.compileHTMLTemplate(input)

    context = simpleTALES.Context()
    # Add a string to the context under the variable title
    context.addGlobal ("title", "Colours of the rainbow")

    # A list of strings
    colours = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]
    # Add the list to the context under the variable rainbow
    context.addGlobal ("rainbow", colours)

    output = cStringIO.StringIO()
    template.expand(context, output)
    return output.getvalue()

Don't forget to add import cStringIO and from simpletal import simpleTal, simpleTALES. Make a TAL template file in the same directory.

    <h1 tal:content="title">The title</h1>
    <ul tal:repeat="colour rainbow">
      <li tal:content="colour">Colour of the rainbow</li>
      <p tal:content="python: str (colour) + ' is the colour'"></p>

</body> </html>

Browse to https://yourdomain/web/tests/

Example of accessing model data via https://yourdomain/web/tests/example

    def example(self, req, mod=None, **kwargs):

        # newSession invokes the authenticate method of session i.e.
        # req.session.authenticate(db, login, password)
        uid = self.newSession(req)

        # open template file and compile
        input = open('addons/web/controllers/taltest.html', 'r')
        template = simpleTAL.compileHTMLTemplate(input)

        # instantiate TAL template context
        context = simpleTALES.Context()

        # Add a string to the context under the variable title
        context.addGlobal ("title", "NAICS Ids")

        # do_search_read is borrowed in whole from main.py
        # naics.code is a custom model for NAICS code data
        ids = self.do_search_read(req, 'naics.code', ['id', 'code', 'title'], 0, 100, [], None)

        # pass search result to the TAL context
        context.addGlobal ("records", ids['records'])

        # pass rendered template to httprequest
        output = cStringIO.StringIO()
        template.expand(context, output)
        return output.getvalue()

        <h1 tal:content="title">The title</h1>
          <li tal:repeat="record records"><span tal:content="record/id">id</span> | <span tal:content="record/code">code</span> | <span tal:content="record/title">title</span></li>

addons/web/controllers/main.py has many helpful methods you can subvert as needed...

Further development on this bearing fruit... image descriptionimage descriptionimage description More detailed example of view code:

    def vendor_messages(self, req, vid=None, **kwargs):
        """Returns a TAL view displaying all OpenERP messages for the current Vendor.
        @param vid: Vendor ID for logged-in user.
        @return Compiled and expanded TAL template.
        table_js = """


        messages = []
        message = None
        partner_ids = None
        vendor_fields = ['company', 'vuid'] # Not using fields_get to prevent sensitive data from escaping into the wild.
        email_fields = ['type', 'email_from', 'author_id', 'partner_ids', 'subject', 'date', 'body', 'message_id', 'to_read']
        #uid = req.session._uid
        uid = newSession(req) # AJAX calls from jQuery require a new session.
        input = open('openerp/server/openerp/addons/web/septa/vendor_messages.html', 'r') # Get TAL template.
        template = simpleTAL.compileHTMLTemplate(input)
        if vid is not None:
            try: # Find the OpenERP user for the current Vendor.
                res = do_search_read(req, 'dbe.vendor', vendor_fields, 0, False, [('id', '=', vid)], None)
            except Exception:
                _logger.debug('<vendor_messages> Session expired or Vendor not found for vendor ID: %s', vid)   
            # Obtain partner_id with user_id to use with finding OpenERP messages for the Vendor.   
            if res is not None and res['length'] > 0:
                for record in res['records']:
                    vuid = record['vuid'][0]
                    partner_ids = get_partner_id(req, vuid)['records'][0]
                    if partner_ids is not None:
                        pid = partner_ids['partner_id'][0]
                        try: # Check the mail.
                            message = do_search_read(req, 'mail.message', email_fields, 0, False, [('partner_ids', 'in', pid)], None)
                        except Exception:
                            _logger.debug('<vendor_messages>Messages not found for vendor ID: %s', vuid)    
                        if message['length'] > 0:                                       
                            for m in messages[0]: # This is ugly find a better way to handle this.
                                if m['email_from'] is False:
                                    m['author_id'] = m['author_id'][1]
                                    del m['email_from']
                                    m['author_id'] = m['email_from']
                                    del m['email_from']

        # Create hidden fields with required values for jQuery reply form.
        formhtml = []
        formhtml.append("""<input id="uid" type="hidden" name="uid" value="%s" />""" %vuid)
        formhtml.append("""<input id="vid" type="hidden" name="vid" value="%s" />""" %vid)
        formhtml.append("""<input id="pid" type="hidden" name="pid" value="%s" />""" %pid)
        script = """var message_data = {"messages":""" + simplejson.dumps(messages[0]) + """};\n""" 
        script += table_js  # Collect Javascript and JSON object for return.
        req.session._suicide = True
        context = simpleTALES.Context()
        # Append context with display data for TAL template.
        context.addGlobal ("title", "SEPTA Vendor Messages")
        context.addGlobal ("script", script)
        context.addGlobal ("header", "Click on the plus sign in the table below to read message.")
        context.addGlobal ("messages", messages[0])
        context.addGlobal ("formhtml", formhtml)
        # Spit out expanded TAL template to the request.
        output = cStringIO.StringIO()
        template.expand(context, output)
        return output.getvalue()

More detailed example of TAL template.

<!-- Vendor contacts Data Template Begin -->
<p tal:content="title">
<p tal:content="header">
    <table id="messages" class="expandable">
            <th> </th>
        <p tal:repeat="message messages" tal:omit-tag="">
            <td tal:content="message/date">07/04/1776</td>
            <td class="alignright"><b tal:condition="message/to_read">NEW: </b><span tal:replace="message/subject">subject</span></td>
            <td tal:content="message/author_id">email-author</td>
            <td tal:content="message/date">07/04/1776</td>
            <td colspan="2"><span tal:replace="structure message/body">message body</span></td>
      <td tal:content="message/date">07/04/1776</td>
      <td tal:content="message/id">&nbsp;</td>
      <td><a href=#>Reply</a></td>
<script type="text/javascript" tal:content="structure script">

<form id="email_reply">
  <p tal:repeat="item formhtml" tal:omit-tag="">
        <span tal:replace="structure item" />
<!-- Vendor contacts Data Template End -->

Your Answer

Please try to give a substantial answer. If you wanted to comment on the question or answer, just use the commenting tool. Please remember that you can always revise your answers - no need to answer the same question twice. Also, please don't forget to vote - it really helps to select the best questions and answers!

About This Community

This community is for professionals and enthusiasts of our products and services. Read Guidelines

Question tools

1 follower(s)


Asked: 3/27/13, 10:54 AM
Seen: 1583 times
Last updated: 3/16/15, 8:10 AM