Search code examples
pythonodooqweb

How to directly access a python method in kanban view templates in Odoo 12?


I have a kanban view with a template in Odoo 12 and I need to access a python method data there to print them in a table. My python method returns a dictionary of key-value pairs.

I used t-foreach as below:

<t t-foreach="get_departments()" t-as="item">
    <tr>
        <td class="text-right">
            <t t-esc="item"/>
        </td>
        <td class="text-right">
            <t t-esc="item_value"/>
        </td>
    </tr>
</t>

And this is the method in my model:

def get_departments(self):
        dep_patients = {}
        departments = self.env['hr.department'].search([('patient_depatment', '=', True)])
        appointment = self.env['hms.appointment'].search([])
        for dept in departments:
            couter = 0
            for app in appointment:
                if dept.id == app.department_id.id:
                    couter +=1
            dep_patients.update({dept.name: couter})

        return dep_patients

in my template, on method call upon page loading I got this error:

Uncaught Error: QWeb2 - template['kanban-box']: Runtime Error: TypeError: dict.get_departments is not a function
http://localhost:8000/web/content/862-f2fdf49/web.assets_common.js:3374
Traceback:
Error: QWeb2 - template['kanban-box']: Runtime Error: TypeError: dict.get_departments is not a function
    at Object.exception (http://localhost:8000/web/content/862-f2fdf49/web.assets_common.js:3374:7)
    at Engine.eval (eval at _render (http://localhost:8000/web/content/862-f2fdf49/web.assets_common.js:3416:73), <anonymous>:114:29)
    at Engine._render (http://localhost:8000/web/content/862-f2fdf49/web.assets_common.js:3415:296)
    at Engine.render (http://localhost:8000/web/content/862-f2fdf49/web.assets_common.js:3415:151)
    at Engine._render (http://localhost:8000/web/content/862-f2fdf49/web.assets_common.js:3419:57)
    at Engine.render (http://localhost:8000/web/content/862-f2fdf49/web.assets_common.js:3415:151)
    at Class._render (http://localhost:8000/web/content/901-66db042/web.assets_backend.js:1804:451)
    at Class.start (http://localhost:8000/web/content/901-66db042/web.assets_backend.js:1794:1256)
    at Class.prototype.<computed> [as start] (http://localhost:8000/web/content/862-f2fdf49/web.assets_common.js:3538:488)
    at http://localhost:8000/web/content/862-f2fdf49/web.assets_common.js:3683:52

As the error shows it seems that my python method is not accessible in the template and I may need to define a JavaScript method for accessing python method data in this case. Is there any way to directly access my python method in a template of Kanban view or not? if yes, how should I do it?


Solution

  • I know that you can call a function in QWeb report.

        <t t-set="result" t-value="o.call_some_method()"/>
    

    But I think you cannot do that in Kanban view because, you cannot access the RecordSet by any variable it's in the client side and calling a function it's not simple as that it's an rcp call as I remember.

    But you can work arround this by using a computed field like in Odoo account module (odoo 10.0).

       department_list = fields.Text('Departments', compute='get_departments')
    
    
    
       @api.one
       def get_departments(self):
           """ use SQL to enhance performance."""
           dep_patients  = []
           computing_sql = """
                SELECT
                     hp.departement_id,
                     hd.name,
                     count(*) as appointment_count
                FROM 
                      hr_department hd 
    
                INNER JOIN hms_appointment hp on hd.id hp.departement_id
    
                WHERE
                     hd.patient_depatment is True
                GROUP BY departement_id, hd.name
                """
            self.env.cr.execute(computing_sql)
            for dp_id, dp_name, counts in self.env.cr.fetchall():
               # add an dict to use it as a json object later in javascript
               dep_patients.append({'name':dp_name, 'count': counts})
    
            self.department_list = json.dumps(dep_patients) if dep_patients else False
    

    and in your view just do

       <t t-value="JSON.parse(record.department_list.raw_value)" t-set="department_list"/>
    
       <t t-foreach="department_list" t-as="item">
            <!-- here item is an json object with two attributes name, count -->
            <tr>
                <td class="text-right">
                    <t t-esc="item.name"/>
                </td>
                <td class="text-right">
                    <t t-esc="tem.count"/>
                </td>
            </tr>
        </t>
    

    Sorry for syntax errors Hope you get the idea, you can check this in account model of odoo