Odoo – Membuat Controller Bag 2

Pada bagian pertama kita sudah membahas bagaimana membuat controller pada Odoo sebagai service api. Pada bagian ini kita akan membuat controller untuk merender view (tampilan html) dan mengolah input user.

Render view dari 0

Odoo sudah menyediakan template untuk view, dimana file jquery, bootstrap dan file-file lainnya sudah diload, terutama jika kita meng-install module website. Tapi pada bagian ini kita akan membahas terlebih dahulu bagaimana membuat view dari 0, tanpa meng-inherit view dari module website.

Pertama buat controller.

@http.route('/sale/list', type='http')
def get_sale_list(self, **kwargs):

    orders = request.env['sale.order'].sudo().search([])

    data = {
        'orders' : orders 
    }
    
    return request.render('tutorial_controller.sale_list', data)

Perhatikan method render diatas. Parameter pertama adalah view / template yang akan kita render. Format penulisannya adalah nama_module.id_template_view. Sedangkan parameter kedua adalah data yang akan kita kirim ke view dengan tipe data berupa dictionary.

Selanjutnya kita buat view / template-nya.

<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <template id="sale_list" name="Daftar Sales">&amp;lt;!DOCTYPE html&amp;gt;
        <html>
            <head>
                <title>Latihan Controller Odoo</title>

                <!-- CDN Asset -->
                <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"/>
                <script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

                <!-- Custom Asset -->
                <link rel="stylesheet" href="/tutorial_controller/static/css/custom.css"/>
                <script type="text/javascript" src="/tutorial_controller/static/js/custom.js"></script>
            </head>
        </html>
        <body>
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h2 class="sale-title">Daftar Sales Order</h2>
                        <table class="table table-hover">
                            <tr>
                                <th>No Dokumen</th>
                                <th>Customer</th>
                                <th>Total</th>
                                <th>Action</th>
                            </tr>
                            <t t-foreach="orders" t-as="order">
                                <tr>
                                    <td>
                                        <t t-esc="order.name" />
                                    </td>
                                    <td>
                                        <t t-esc="order.partner_id.name" />
                                    </td>
                                    <td>
                                        <t t-esc="order.amount_total" />
                                    </td>
                                    <td>
                                        <button class="btn btn-sm btn-danger btn-delete-sale" t-att-data-sale-number="order.name">Delete</button>
                                    </td>
                                </tr>
                            </t>
                        </table>
                    </div>
                </div>
            </div>
        </body>
    </template>
</odoo>

Pada satu module, id suatu template / view harus unik. Misal pada kode diatas kita menggunakan id sale_list. Maka kita tidak bisa menggunakan id ini di file lain di module yang sama, tetapi bisa digunakan di module yang berbeda. Oleh karena itu dicontroller saat kita me-render view kita perlu memasukkan nama module-nya.

Untuk me-load file css dan javascript format penulisan path-nya adalah /nama_module/nama_folder_dan_nama_file. Dan pastikan module yang terdapat file tersebut sudah diinstall.

Untuk menampilkan data dari controller di view kita menggunakan Qweb templating. Qweb adalah templating bawaan odoo untuk mengolah html. Klik link berikut untuk lebih tahu mengenai Qweb

Jika kita membuka http://localhost:8069/sale/list kira-kira tampilannya akan seperti ini

Inherit dari module Website

Untuk membuat view yang inherit ke module website, kita perlu menambahkan parameter website di controller. Misalnya seperti ini.

@http.route('/web/sale/list', type='http', website=True)
def get_web_sale_list(self, **kwargs):

    orders = request.env['sale.order'].sudo().search([])

    data = {
        'orders' : orders 
    }
    
    return request.render('tutorial_controller.website_sale_list', data)

Perlu kita ketahui module website sudah me-load file bootstrap, jquery dll di template website.assets_frontend jadi kita perlu inherit ke template tersebut untuk memasukkan file css dan javascript custom milik kita. Seperti ini contohnya.

<template id="assets_frontend_inherit" inherit_id="website.assets_frontend">
    <!-- masukkan file css custom paling bawah -->
    <xpath expr="link[last()]" position="after">
        <link rel="stylesheet" href="/tutorial_controller/static/css/custom.css"/>
    </xpath>
    <!-- masukkan file javascript custom paling bawah -->
    <xpath expr="script[last()]" position="after">
        <script type="text/javascript" src="/tutorial_controller/static/js/custom.js"></script>
    </xpath>
</template>

Terakhir adalah membuat view. Yang perlu anda perhatikan adalah jangan lupa memanggil template website.layout agar navbar dan menu-menu-nya tampil. Seperti kode dibawah ini

<template id="website_sale_list" name="Daftar Sales Website">
    <!-- panggil view website.layout agar navbar dll tampil -->
    <t t-call="website.layout">
        <!-- tambah judul halaman -->
        <t t-set="additional_title" t-value="'Daftar Sales'" />
        <div id="wrap">
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h2 class="sale-title">Daftar Sales Order</h2>
                        <table class="table table-hover">
                            <tr>
                                <th>No Dokumen</th>
                                <th>Customer</th>
                                <th>Total</th>
                                <th>Action</th>
                            </tr>
                            <t t-foreach="orders" t-as="order">
                                <tr>
                                    <td>
                                        <t t-esc="order.name" />
                                    </td>
                                    <td>
                                        <t t-esc="order.partner_id.name" />
                                    </td>
                                    <td>
                                        <t t-esc="order.amount_total" />
                                    </td>
                                    <td>
                                        <button class="btn btn-sm btn-danger btn-delete-sale" t-att-data-sale-number="order.name">Delete</button>
                                    </td>
                                </tr>
                            </t>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </t>
</template>

Tampilan akhirnya akan jadi seperti ini.

Menangani Form

Buat 2 controller. Controller pertama berfungsi untuk merender form, sedangkan controller kedua untuk mengolah data-nya.

@http.route('/sale/support', type='http', website=True)
def sale_support(self, **kwargs):
    # controller ini hanya untuk merender form
    return request.render('tutorial_controller.sale_support')

@http.route('/sale/support/response', type='http', website=True)
def sale_support_response(self, **kwargs):
    # controller ini untuk menerima input user
    # input user disimpan di parameter kwargs singkatan dari keyword argument
    # kwargs ini bisa diganti dengan nama lain misal post atau data
    # kwargs bertipe distionary

    data = {
        'name' : kwargs.get('name',''),
        'email' : kwargs.get('email',''),
        'issue' : kwargs.get('issue','')
    }
    
    return request.render('tutorial_controller.sale_support_response', data)

Selanjutnya buat 2 buah view juga.

<template id="sale_support" name="Sales Support">
    <t t-call="website.layout">
        <t t-set="additional_title" t-value="'Sales Support'" />
        <div id="wrap">
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h2 class="sale-title">Sales Support</h2>   
                        <form action="/sale/support/response" method="post">
                            <!-- 
                                set csrf token, agar lebih secure,
                                jika tidak diset, pastikan pada controller paremeter csrf diset False
                            -->
                            <input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
                            <div class="row">
                                <div class="col-md-6">
                                    <div class="form-group">
                                        <label class="col-form-label">Nama</label>
                                        <input type="text" name="name" class="form-control" />
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <div class="form-group">
                                        <label class="col-form-label">Email</label>
                                        <input type="email" name="email" class="form-control" />
                                    </div>
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-12">
                                    <div class="form-group">
                                        <label class="col-form-label">Keluhan</label>
                                        <textarea rows="5" class="form-control" name="issue"></textarea>
                                    </div>
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-12">
                                    <button type="submit" class="btn btn-success">Kirim</button>
                                </div>
                            </div>
                        </form>                     
                    </div>                      
                </div>
            </div>
        </div>
    </t>
</template>

<template id="sale_support_response" name="Sales Support Response">
    <t t-call="website.layout">
        <t t-set="additional_title" t-value="'Sales Support'" />
        <div id="wrap">
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h2 class="sale-title">Sales Support</h2>   
                        <h3>Terima kasih atas feedback anda. Berikut ini adalah data yang anda masukkan</h3>
                        <h3>Nama : <t t-esc="name"/></h3>
                        <h3>Email : <t t-esc="email"/></h3>     
                        <h3>Keluhan : <t t-esc="issue"/></h3>   
                    </div>                      
                </div>
            </div>
        </div>
    </t>
</template>

Jika kita ketik alamat http://localhost:8069/sale/support akan muncul form seperti dibawah ini.

Jika kita isi dan klik tombol kirim akan diarahkan ke halaman http://localhost:8069/sale/support/response dengan tampilan seperti dibawah ini.

Demikian tutorial controller pada odoo bagian kedua ini. Jika ada kesempatan pada bagian selanjutnya kita akan membahas bagaimana menangani file upload dan download serta cara override controller atau view yang sudah ada.

Download Source Code

Tulisan Serupa

7 Replies to “Odoo – Membuat Controller Bag 2”

  1. Om ngasturi, mau tanya kalau misalkan kita bikin menu baru terus ketika diklik langsung menuju ke url httpRoute yg sudah dibuat bagaimana ya.. mohon penjelasannya
    terima kasih

    1. Kalau di backend pakai ir.actions.act_url nanti taruh route/url-nya di key url, kayak kode ini

      <record id="action_open_google" model="ir.actions.act_url">
          <field name="name">Open Google</field>
          <field name="type">ir.actions.act_url</field>
          <field name="target">self</field>
          <field name="url">https://google.com</field>
      </record>
      
      <menuitem id="menu_open_google"
          name="Open Google"
          action="action_open_google"
          parent="sale.sale_order_menu" />
      

      Kalau di e-commerce atur di menu Website >> Configuration >> Menus

  2. bisa tidak ya kita koneksikan frontendnya dengan alpine js?
    saya sudah coba masukin script di tag headnya, beberapa fungsi di alpinejs lumayan work seperti x-data, x-text di property dari divnya seperti berikut:

    tapi ketika saya menggunakan x-on:click atau @click maka muncul error seperti berikut

    lxml.etree.XMLSyntaxError: Namespace prefix x-on for click on button is not defined, line 27, column 37

    dan

    lxml.etree.XMLSyntaxError: error parsing attribute name, line 27, column 13

    kira2 ada solusi tidak ya

    1. kalau pakai QWEB template (model ir.ui.view) gak bisa pak, karena dia pakai format xml, attribute x-on:click bukan merupakan attribute yang valid di xml. text :click lah yang bikin dia tidak valid, kalau hanya x-on dia valid. solusinya pakai file html static. berikut ini adalah contoh file html static. dan berikut ini adalah contoh bagaimana merender file html static dari controller.

    1. sudah beda module, beda series tutorial juga. yang custom_sale itu seri membuat module odoo, ada 7 tulisan kalau gak salah, yang controller ini seri lain, ada 3 tulisan, yang sebaiknya dibaca setelah menuntaskan seri yang membuat module odoo, atau sudah bisa buat module odoo sebelumnya

Leave a Reply