hunk.code_window:           <h3>Suggested alternatives:</h3>
             <div class='row mt16' style="">
             <t t-foreach="product.alternative_product_ids" t-as="product">
                 <div class='col-md-2 thumbnail' style='width: 170px; height:130px; float:left; display:inline; margin-right: 10px;'>
                     <div class='mt16 text-center'>
                         <span t-field="product.image_small" t-field-options='{"widget": "image", "class": "img-rounded shadow" }'/>
                         <h5>
                             <a t-attf-href="/shop/product/#{ slug(product) }" style="display: block">
  
hunk.labels: keep keep keep keep keep replace keep keep
hunk.after_edit:                       <span t-field="product.image_small" t-field-options='{"widget": "image", "class": "img-rounded shadow o_alternative_product" }'/>
  
hunk.file_path: addons/website_sale/views/templates.xml
hunk.type: replace
file: :banner: banners/odoo_guideline.jpg
  
  .. highlight:: python
  
  ===============
  Odoo Guidelines
  ===============
  
  This page introduce the new Odoo Coding Guidelines. These guidelines
  aim to improve the quality of the code (better readability of source,
  ...) and  Odoo Apps. Indeed, proper code ought ease maintenance, aid
  debugging, lower complexity and promote reliability.
  
  Module structure
  ================
  
  Directories
  -----------
  A module is organised in a few directory :
  
  - *data/* : demo and data xml
  - *models/* : models definition
  - *controllers/* : contains controllers (http routes).
  - *views/* : contains the views and templates
  - *static/* : contains the web assets, separated into *css/, js/, img/, lib/, ...*
  
  File naming
  -----------
  For *views* declarations, split backend views from (frontend)
  templates in 2 differents files.
  
  For *models*, split the business logic by sets of models, in each set
  select a main model, this model gives its name to the set. If there is
  only one model, its name is the same as the module name. For
  each set named <main_model> the following files may be created:
  
  - :file:`models/{<main_model>}.py`
  - :file:`models/{<inherited_main_model>}.py`
  - :file:`views/{<main_model>}_templates.xml`
  - :file:`views/{<main_model>}_views.xml`
  
  For instance, *sale* module introduces ``sale_order`` and
  ``sale_order_line`` where ``sale_order`` is dominant. So the
  ``<main_model>`` files will be named :file:`models/sale_order.py` and
  :file:`views/sale_order_views.py`.
  
  
  For *data*, split them by purpose : demo or data. The filename will be
  the main_model name, suffixed by *_demo.xml* or *_data.xml*.
  
  For *controller*, the only file should be named *main.py*.
  
  For *static files*, the name pattern is *<module_name>.ext* (i.e. :
  static/js/im_chat.js, static/css/im_chat.css, static/xml/im_chat.xml,
  ...). Don't link data (image, libraries) outside Odoo : don't use an
  url to an image but copy it in our codebase instead.
  
  The complete tree should look like
  
  .. code-block:: text
  
      addons/<my_module_name>/
      |-- __init__.py
      |-- __openerp__.py
      |-- controllers/
      |   |-- __init__.py
      |   `-- main.py
      |-- data/
      |   |-- <main_model>_data.xml
      |   `-- <inherited_main_model>_demo.xml
      |-- models/
      |   |-- __init__.py
      |   |-- <main_model>.py
      |   `-- <inherited_main_model>.py
      |-- security/
      |   |-- ir.model.access.csv
      |   `-- <main_model>_security.xml
      |-- static/
      |   |-- img/
      |   |   |-- my_little_kitten.png
      |   |   `-- troll.jpg
      |   |-- lib/
      |   |   `-- external_lib/
      |   `-- src/
      |       |-- js/
      |       |   `-- <my_module_name>.js
      |       |-- css/
      |       |   `-- <my_module_name>.css
      |       |-- less/
      |       |   `-- <my_module_name>.less
      |       `-- xml/
      |           `-- <my_module_name>.xml
      `-- views/
          |-- <main_model>_templates.xml
          |-- <main_model>_views.xml
          |-- <inherited_main_model>_templates.xml
          `-- <inherited_main_model>_views.xml
  
  
  .. note:: File names should only contain ``[a-z0-9_]`` (lowercase
            alphanumerics and ``_``)
  
  .. warning:: Use correct file permissions : folder 755 and file 644.
  
  XML files
  =========
  
  Format
  ------
  When declaring a record in XML,
  
  - Place ``id`` attribute before ``model``
  - For field declaration, ``name`` attribute is first. Then place the
    *value* either in the ``field`` tag, either in the ``eval``
    attribute, and finally other attributes (widget, options, ...)
    ordered by importance.
  
  - Try to group the record by model. In case of dependencies between
    action/menu/views, the convention may not be applicable.
  - Use naming convention defined at the next point
  - The tag *<data>* is only used to set not-updatable data with ``noupdate=1``
  
  .. code-block:: xml
  
      <record id="view_id" model="ir.ui.view">
          <field name="name">view.name</field>
          <field name="model">object_name</field>
          <field name="priority" eval="16"/>
          <field name="arch" type="xml">
              <tree>
                  <field name="my_field_1"/>
                  <field name="my_field_2" string="My Label" widget="statusbar" statusbar_visible="draft,sent,progress,done" statusbar_colors='{"invoice_except":"red","waiting_date":"blue"}' />
              </tree>
          </field>
      </record>
  
  
  Naming xml_id
  -------------
  
  Security, View and Action
  ~~~~~~~~~~~~~~~~~~~~~~~~~
  
  Use the following pattern :
  
  * For a menu: :samp:`{<model_name>}_menu`
  * For a view: :samp:`{<model_name>}_view_{<view_type>}`, where *view_type* is
    ``kanban``, ``form``, ``tree``, ``search``, ...
  * For an action: the main action respects :samp:`{<model_name>}_action`.
    Others are suffixed with :samp:`_{<detail>}`, where *detail* is a
    lowercase string briefly explaining the action.
    This is used only if multiple actions are declared for the
    model.
  * For a group: :samp:`{<model_name>}_group_{<group_name>}` where *group_name*
    is the name of the group, generally 'user', 'manager', ...
  * For a rule: :samp:`{<model_name>}_rule_{<concerned_group>}` where
    *concerned_group* is the short name of the concerned group ('user'
    for the 'model_name_group_user', 'public' for public user, 'company'
    for multi-company rules, ...).
  
  .. code-block:: xml
  
      <!-- views and menus -->
      <record id="model_name_menu" model="ir.ui.menu">
          ...
      </record>
  
      <record id="model_name_view_form" model="ir.ui.view">
          ...
      </record>
  
      <record id="model_name_view_kanban" model="ir.ui.view">
          ...
      </record>
  
      <!-- actions -->
      <record id="model_name_action" model="ir.actions.act_window">
          ...
      </record>
  
      <record id="model_name_action_child_list" model="ir.actions.act_window">
          ...
      </record>
  
      <!-- security -->
      <record id="model_name_group_user" model="res.groups">
          ...
      </record>
  
      <record id="model_name_rule_public" model="ir.rule">
          ...
      </record>
  
      <record id="model_name_rule_company" model="ir.rule">
          ...
      </record>
  
  
  
  .. note:: View names use dot notation ``my.model.view_type`` or
            ``my.model.view_type.inherit`` instead of *"This is the form view of
            My Model"*.
  
  
  Inherited XML
  ~~~~~~~~~~~~~
  
  The naming pattern of inherited view is
  :samp:`{<base_view>}_inherit_{<current_module_name>}`. A module may only
  extend a view once.  Suffix the orginal name with
  :samp:`_inherit_{<current_module_name>}` where *current_module_name* is the
  technical name of the module extending the view.
  
  
  .. code-block:: xml
  
      <record id="inherited_model_view_form_inherit_my_module" model="ir.ui.view">
          ...
      </record>
  
  
  Python
  ======
  
  PEP8 options
  ------------
  
  Using a linter can help show syntax and semantic warnings or errors. Odoo
  source code tries to respect Python standard, but some of them can be ignored.
  
  - E501: line too long
  - E301: expected 1 blank line, found 0
  - E302: expected 2 blank lines, found 1
  - E126: continuation line over-indented for hanging indent
  - E123: closing bracket does not match indentation of opening bracket's line
  - E127: continuation line over-indented for visual indent
  - E128: continuation line under-indented for visual indent
  - E265: block comment should start with '# '
  
  Imports
  -------
  The imports are ordered as
  
  #. External libraries (one per line sorted and split in python stdlib)
  #. Imports of ``openerp``
  #. Imports from Odoo modules (rarely, and only if necessary)
  
  Inside these 3 groups, the imported lines are alphabetically sorted.
  
  .. code-block:: python
  
      # 1 : imports of python lib
      import base64
      import re
      import time
      # 2 :  imports of openerp
      import openerp
      from openerp import api, fields, models # alphabetically ordered
      from openerp.tools.safe_eval import safe_eval as eval
      from openerp.tools.translate import _
      # 3 :  imports from odoo modules
      from openerp.addons.website.models.website import slug
      from openerp.addons.web.controllers.main import login_redirect
  
  
  Idioms
  ------
  
  - Prefer ``%`` over ``.format()``, prefer ``%(varname)`` instead of position (This is better for translation)
  - Try to avoid generators and decorators
  - Always favor *Readability* over *conciseness* or using the language features or idioms.
  - Use list comprehension, dict comprehension, and basic manipulation using ``map``, ``filter``, ``sum``, ... They make the code easier to read.
  - The same applies for recordset methods : use ``filtered``, ``mapped``, ``sorted``, ...
  - Each python file should have ``# -*- coding: utf-8 -*-`` as first line
  - Use the ``UserError`` defined in ``openerp.exceptions`` instead of overriding ``Warning``, or find a more appropriate exception in *exceptions.py*
  - Document your code (docstring on methods, simple comments for the tricky part of the code)
  - Use meaningful variable/class/method names
  
  
  
  Symbols
  -------
  
  - Odoo Python Class : use camelcase for code in api v8, underscore lowercase notation for old api.
  
  .. code-block:: python
  
      class AccountInvoice(models.Model):
          ...
  
      class account_invoice(osv.osv):
          ...
  
  - Variable name :
      - use camelcase for model variable
      - use underscore lowercase notation for common variable.
      - since new API works with record or recordset instead of id list, don't suffix variable name with *_id* or *_ids* if they not contain id or list of id.
  
  .. code-block:: python
  
      ResPartner = self.env['res.partner']
      partners = ResPartner.browse(ids)
      partner_id = partners[0].id
  
  - ``One2Many`` and ``Many2Many`` fields should always have *_ids* as suffix (example: sale_order_line_ids)
  - ``Many2One`` fields should have *_id* as suffix (example : partner_id, user_id, ...)
  - Method conventions
      - Compute Field : the compute method pattern is *_compute_<field_name>*
      - Search method : the search method pattern is *_search_<field_name>*
      - Default method : the default method pattern is *_default_<field_name>*
      - Onchange method : the onchange method pattern is *_onchange_<field_name>*
      - Constraint method : the constraint method pattern is *_check_<constraint_name>*
      - Action method : an object action method is prefix with *action_*. Its decorator is ``@api.multi``, but since it use only one record, add ``self.ensure_one()`` at the beginning of the method.
  
  - In a Model attribute order should be
      #. Private attributes (``_name``, ``_description``, ``_inherit``, ...)
      #. Default method and ``_default_get``
      #. Field declarations
      #. Compute and search methods in the same order as field declaration
      #. Constrains methods (``@api.constrains``) and onchange methods (``@api.onchange``)
      #. CRUD methods (ORM overrides)
      #. Action methods
      #. And finally, other business methods.
  
  .. code-block:: python
  
      class Event(models.Model):
          # Private attributes
          _name = 'event.event'
          _description = 'Event'
  
          # Default methods
          def _default_name(self):
              ...
  
          # Fields declaration
          name = fields.Char(string='Name', default=_default_name)
          seats_reserved = fields.Integer(oldname='register_current', string='Reserved Seats',
              store=True, readonly=True, compute='_compute_seats')
          seats_available = fields.Integer(oldname='register_avail', string='Available Seats',
              store=True, readonly=True, compute='_compute_seats')
          price = fields.Integer(string='Price')
  
          # compute and search fields, in the same order that fields declaration
          @api.multi
          @api.depends('seats_max', 'registration_ids.state', 'registration_ids.nb_register')
          def _compute_seats(self):
              ...
  
          # Constraints and onchanges
          @api.constrains('seats_max', 'seats_available')
          def _check_seats_limit(self):
              ...
  
          @api.onchange('date_begin')
          def _onchange_date_begin(self):
              ...
  
          # CRUD methods
          def create(self):
              ...
  
          # Action methods
          @api.multi
          def action_validate(self):
              self.ensure_one()
              ...
  
          # Business methods
          def mail_user_confirm(self):
              ...
  
  
  Javascript and CSS
  ==================
  **For javascript :**
  
  - ``use strict;`` is recommended for all javascript files
  - Use a linter (jshint, ...)
  - Never add minified Javascript Libraries
  - Use camelcase for class declaration
  
  **For CSS :**
  
  - Prefix all your class with *o_<module_name>* where *module_name* is the technical name of the module ('sale', 'im_chat', ...) or the main route reserved by the module (for website module mainly, i.e. : 'o_forum' for website_forum module). The only exception for this rule is the webclient : it simply use *o_* prefix.
  - Avoid using id
  - Use bootstrap native class
  - Use underscore lowercase notation to name class
  
  Git
  ===
  
  Commit message
  --------------
  
  Prefix your commit with
  
  - **[IMP]** for improvements
  - **[FIX]** for bug fixes
  - **[REF]** for refactoring
  - **[ADD]** for adding new resources
  - **[REM]** for removing of resources
  - **[MERGE]** for merge commits (only for forward/back-port)
  - **[CLA]** for signing the Odoo Individual Contributor License
  
  Then, in the message itself, specify the part of the code impacted by your changes (module name, lib, transversal object, ...) and a description of the changes.
  
  - Always include a meaningful commit message: it should be self explanatory
    (long enough) including the name of the module that has been changed and the
    reason behind the change. Do not use single words like "bugfix" or
    "improvements".
  - Avoid commits which simultaneously impact multiple modules. Try to
    split into different commits where impacted modules are different
    (It will be helpful if we need to revert a module separately).
  
  .. code-block:: text
  
      [FIX] website, website_mail: remove unused alert div, fixes look of input-group-btn
  
      Bootstrap's CSS depends on the input-group-btn
      element being the first/last child of its parent.
      This was not the case because of the invisible
      and useless alert.
  
      [IMP] fields: reduce memory footprint of list/set field attributes
  
      [REF] web: add module system to the web client
  
      This commit introduces a new module system for the javascript code.
      Instead of using global ...
  
  
  .. note:: Use the long description to explain the *why* not the
            *what*, the *what* can be seen in the diff
  