Створення веб-сайту¶
Небезпека
This tutorial is outdated. We recommend reading Server framework 101 instead.
Попередження
Цей посібник передбачає базове знання Python
This guide assumes an installed Odoo
Створення базового модуля¶
В Odoo завдання виконуються шляхом створення модулів.
Модулі налаштовують поведінку інсталяції Odoo, додаючи нову поведінку або змінюючи існуючу (включаючи поведінку, додану іншими модулями).
Скаффолдинг Odoo може налаштувати базовий модуль. Щоб швидко почати, просто викличте:
$ ./odoo-bin scaffold Academy my-modules
Це автоматично створить my-modules
каталог модулів з модулем academy
всередині. За бажанням каталог може бути існуючим каталогом модуля, але ім’я модуля має бути унікальним у каталозі.
Демонстраційний модуль¶
Маємо «повний» модуль, готовий до встановлення.
Хоча він абсолютно нічого не робить, ми можемо його встановити:
запустіть сервер Odoo
$ ./odoo-bin --addons-path addons,my-modules
перейдіть на http://localhost:8069
створіть нову базу даних, включаючи демонстраційні дані
перейдіть
у верхньому правому куті зніміть фільтр Встановлено та знайдіть academy
натисніть кнопку Встановити для модуля Academy
До браузера¶
Контролери інтерпретують запити браузера та надсилають дані назад.
Додайте простий контролер і переконайтеся, що він імпортований __init__.py
(щоб Odoo міг його знайти):
academy/controllers.py
¶# -*- coding: utf-8 -*-
from odoo import http
class Academy(http.Controller):
@http.route('/academy/academy/', auth='public')
def index(self, **kw):
return "Hello, world"
Вимкніть сервер (^C), а потім перезапустіть його:
$ ./odoo-bin --addons-path addons,my-modules
і відкрийте сторінку за адресою http://localhost:8069/academy/academy/, ви побачите свою «сторінку»:

Шаблони¶
Генерувати HTML на Python не дуже приємно.
Звичайним рішенням є шаблони, псевдодокументи з заповнювачами та логікою відображення. Odoo допускає будь-яку систему шаблонів Python, але надає власну систему шаблонів QWeb, яка інтегрується з іншими функціями.
Створіть шаблон і переконайтеся, що файл шаблону зареєстровано в маніфесті __manifest__.py
, і змініть контролер, щоб використовувати наш шаблон:
academy/controllers.py
¶class Academy(http.Controller):
@http.route('/academy/academy/', auth='public')
def index(self, **kw):
return http.request.render('academy.index', {
'teachers': ["Diana Padilla", "Jody Caroll", "Lester Vaughn"],
})
academy/templates.xml
¶<odoo>
<template id="index">
<title>Academy</title>
<t t-foreach="teachers" t-as="teacher">
<p><t t-esc="teacher"/></p>
</t>
</template>
</odoo>
Шаблони виконують ітерацію (t-foreach
) для всіх вчителів (пропущених через контекст шаблону) і друкують кожного вчителя в окремому абзаці.
Нарешті перезапустіть Odoo та оновіть дані модуля (щоб встановити шаблон), перейшовши до Оновити.
та натиснувшиПорада
Крім того, Odoo можна перезапустити і одночасно оновити модулі
:
$ odoo-bin --addons-path addons,my-modules -d academy -u academy
Перехід до http://localhost:8069/academy/academy/ має призвести до:

Зберігання даних в Odoo¶
Моделі Odoo відображаються в таблицях бази даних.
У попередньому розділі ми просто відобразили список рядків, введених статично в код Python. Це не дозволяє модифікувати або постійне зберігання, тому тепер ми перемістимо наші дані до бази даних.
Визначення моделі даних¶
Визначте модель вчителя та переконайтеся, що її імпортовано з __init__.py
, щоб вона правильно завантажувалася:
academy/models.py
¶from odoo import models, fields, api
class Teachers(models.Model):
_name = 'academy.teachers'
name = fields.Char()
Потім встановіть базовий контроль доступу для моделі та додайте їх до маніфесту:
academy/__manifest__.py
¶# always loaded
'data': [
'security/ir.model.access.csv',
'templates.xml',
],
academy/security/ir.model.access.csv
¶id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0
це просто надає доступ для читання (perm_read
) усім користувачам (group_id:id
залишено порожнім).
Примітка
Файли даних (XML або CSV) мають бути додані до маніфесту модуля, файли Python (моделі чи контролери) ні, але їх потрібно імпортувати з __init__.py
(безпосередньо або опосередковано)
Попередження
користувач-адміністратор обходить контроль доступу, він має доступ до всіх моделей, навіть якщо йому не надано доступ
Демонстраційні дані¶
Другим кроком є додавання деяких демонстраційних даних до системи, щоб можна було легко її протестувати. Це робиться шляхом додавання demo
файлу даних, на який має бути посилання з маніфесту:
academy/demo.xml
¶<odoo>
<record id="padilla" model="academy.teachers">
<field name="name">Diana Padilla</field>
</record>
<record id="carroll" model="academy.teachers">
<field name="name">Jody Carroll</field>
</record>
<record id="vaughn" model="academy.teachers">
<field name="name">Lester Vaughn</field>
</record>
</odoo>
Порада
Файли даних можна використовувати для демонстраційних і недемонстраційних даних. Демонстраційні дані завантажуються лише в «демонстраційному режимі» і можуть використовуватися для тестування потоку та демонстрації, недемонстраційні дані завжди завантажуються та використовуються як початкове налаштування системи.
У цьому випадку ми використовуємо демонстраційні дані, тому що фактичний користувач системи хотів би ввести або імпортувати власний список викладачів, цей список корисний лише для тестування.
Доступ до даних¶
Останнім кроком є зміна моделі та шаблону для використання наших демонстраційних даних:
отримати записи з бази даних замість статичного списку
Оскільки
search()
повертає набір записів, які відповідають фільтру (тут «усі записи»), змініть шаблон, щоб надрукуватиname
кожного вчителя
academy/controllers.py
¶class Academy(http.Controller):
@http.route('/academy/academy/', auth='public')
def index(self, **kw):
Teachers = http.request.env['academy.teachers']
return http.request.render('academy.index', {
'teachers': Teachers.search([])
})
academy/templates.xml
¶<odoo>
<template id="index">
<title>Academy</title>
<t t-foreach="teachers" t-as="teacher">
<p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>
</t>
</template>
</odoo>
Перезапустіть сервер і оновіть модуль (щоб оновити маніфест і шаблони та завантажити демонстраційний файл), а потім перейдіть до http://localhost:8069/academy/academy/. Сторінка має виглядати трохи по-іншому: перед іменами має бути просто число (ідентифікатор бази даних для вчителя).
Підтримка сайту¶
Odoo містить модуль, призначений для створення веб-сайтів.
Поки що ми використовували контролери досить безпосередньо, але Odoo 8 додав глибшу інтеграцію та кілька інших послуг (наприклад, стиль за замовчуванням, оформлення тем) через модуль website
.
спочатку додайте
website
як залежність відacademy
потім додайте прапор
website=True
до контролера, це встановлює кілька нових змінних для об’єкта запиту і дозволяє використовувати макет веб-сайту в нашому шаблонівикористовуйте макет веб-сайту в шаблоні
academy/__manifest__.py
¶'version': '0.1',
# any module necessary for this one to work correctly
'depends': ['website'],
# always loaded
'data': [
academy/controllers.py
¶class Academy(http.Controller):
@http.route('/academy/academy/', auth='public', website=True)
def index(self, **kw):
Teachers = http.request.env['academy.teachers']
return http.request.render('academy.index', {
'teachers': Teachers.search([])
})
academy/templates.xml
¶<odoo>
<template id="index">
<t t-call="website.layout">
<t t-set="title">Academy</t>
<div class="oe_structure">
<div class="container">
<t t-foreach="teachers" t-as="teacher">
<p><t t-esc="teacher.id"/> <t t-esc="teacher.name"/></p>
</t>
</div>
</div>
</t>
</template>
</odoo>
Після перезапуску сервера під час оновлення модуля (щоб оновити маніфест і шаблон) доступ до http://localhost:8069/academy/academy/ має призвести до кращого вигляду сторінки з брендингом і низкою вбудованих елементів сторінки (угорі -меню рівня, нижній колонтитул, …)

Макет веб-сайту також підтримує інструменти редагування: натисніть Увійти (у верхньому правому куті), заповніть облікові дані (admin
/ admin
за замовчуванням), а потім натисніть :guilabel: Увійти
.
Тепер ви перебуваєте в «справжньому» Odoo: адміністративний інтерфейс. Наразі натисніть на пункт меню Веб-сайт (верхній лівий кут.
Ми знову на веб-сайті, але як адміністратор, із доступом до розширених функцій редагування, які надає служба підтримки веб-сайту:
редактор коду шаблону (
), де ви можете переглядати та редагувати всі шаблони, що використовуються для поточної сторінкикнопка Редагувати у верхньому лівому куті перемикає в «режим редагування», де доступне редагування блоків (фрагментів) і форматованого тексту
ряд інших функцій, таких як мобільний попередній перегляд або SEO
URL-адреси та маршрутизація¶
Методи контролера пов’язані з маршрутами через декоратор route()
, який приймає рядок маршрутизації та ряд атрибутів для налаштування поведінки чи безпеки.
Ми бачили «літеральний» рядок маршрутизації, який точно відповідає розділу URL-адреси, але рядки маршрутизації також можуть використовувати шаблони конвертера, які відповідають бітам URL-адрес і роблять їх доступними як локальні змінні. Наприклад, ми можемо створити новий метод контролера, який приймає трохи URL-адреси та друкує її:
academy/controllers.py
¶# New route
@http.route('/academy/<name>/', auth='public', website=True)
def teacher(self, name):
return '<h1>{}</h1>'.format(name)
перезапустіть Odoo, перейдіть на http://localhost:8069/academy/Alice/ і http://localhost:8069/academy/Bob/ і побачите різницю.
Як видно з назви, шаблони конвертера не просто витягують, вони також виконують перевірку та перетворення, тому ми можемо змінити новий контролер, щоб він приймав лише цілі числа:
academy/controllers.py
¶@http.route('/academy/<int:id>/', auth='public', website=True)
def teacher(self, id):
return '<h1>{} ({})</h1>'.format(id, type(id).__name__)
Перезапустіть Odoo, відкрийте http://localhost:8069/academy/2, зверніть увагу, що старе значення було рядком, а нове було перетворено на цілі числа. Спробуйте отримати доступ до http://localhost:8069/academy/Carol/ і зауважте, що сторінку не знайдено: оскільки «Carol» не є цілим числом, маршрут проігноровано, і маршрут не знайдено.
Odoo надає додатковий конвертер, який називається model
, який надає записи безпосередньо після отримання їх ідентифікатора. Давайте використаємо це, щоб створити загальну сторінку для біографій вчителів:
academy/controllers.py
¶@http.route('/academy/<model("academy.teachers"):teacher>/', auth='public', website=True)
def teacher(self, teacher):
return http.request.render('academy.biography', {
'person': teacher
})
academy/templates.xml
¶<template id="biography">
<t t-call="website.layout">
<t t-set="title">Academy</t>
<div class="oe_structure"/>
<div class="oe_structure">
<div class="container">
<h3><t t-esc="person.name"/></h3>
</div>
</div>
<div class="oe_structure"/>
</t>
</template>
потім змініть список моделей, щоб зв’язати наш новий контролер:
academy/templates.xml
¶<template id="index">
<t t-call="website.layout">
<t t-set="title">Academy</t>
<div class="oe_structure">
<div class="container">
<t t-foreach="teachers" t-as="teacher">
<p>
<a t-attf-href="/academy/{{ slug(teacher) }}">
<t t-esc="teacher.name"/></a>
</p>
</t>
</div>
</div>
</t>
</template>
Перезапустіть Odoo та оновіть модуль, після чого ви зможете відвідати сторінку кожного вчителя. Як вправу, спробуйте додати блоки на сторінку вчителя, щоб написати біографію, а потім перейдіть на сторінку іншого вчителя і так далі. Ви побачите, що ваша біографія є спільною для всіх викладачів, оскільки блоки додаються до шаблону, а шаблон біографії є спільною для всіх викладачів, коли редагується одна сторінка, вони редагуються одночасно.
Редагування полів¶
Дані, які є специфічними для запису, повинні зберігатися в цьому записі, тому давайте додамо нове поле біографії для наших викладачів:
academy/models.py
¶class Teachers(models.Model):
_name = 'academy.teachers'
name = fields.Char()
biography = fields.Html()
academy/templates.xml
¶<template id="biography">
<t t-call="website.layout">
<t t-set="title">Academy</t>
<div class="oe_structure"/>
<div class="oe_structure">
<div class="container">
<h3><t t-esc="person.name"/></h3>
<div><t t-esc="person.biography"/></div>
</div>
</div>
<div class="oe_structure"/>
</t>
</template>
Перезапустіть Odoo та оновіть представлення, перезавантажте сторінку вчителя і… поле стане невидимим, оскільки воно нічого не містить.
Для полів запису шаблони можуть використовувати спеціальну директиву t-field
, яка дозволяє редагувати вміст полів із веб-сайту за допомогою інтерфейсів для окремих полів. Змініть шаблон person на використання t-field
:
academy/templates.xml
¶<div class="oe_structure">
<div class="container">
<h3 t-field="person.name"/>
<div t-field="person.biography"/>
</div>
</div>
Перезапустіть Odoo та оновіть модуль, тепер є покажчик місця заповнення під іменем вчителя та нова зона для блоків у режимі Редагувати. Вміст, опущений туди, зберігається у відповідному полі біографії
вчителя, і, таким чином, є специфічним для цього вчителя.
Ім’я вчителя також можна редагувати, і після збереження зміни видно на сторінці індексу.
t-field
також може приймати параметри форматування, які залежать від точного поля. Наприклад, якщо ми відображаємо дату зміни для запису вчителя:
academy/templates.xml
¶<div class="oe_structure">
<div class="container">
<h3 t-field="person.name"/>
<p>Last modified: <i t-field="person.write_date"/></p>
<div t-field="person.biography"/>
</div>
</div>
він відображається дуже «комп’ютерним» способом і його важко прочитати, але ми можемо попросити версію, зрозумілу людині:
academy/templates.xml
¶<div class="oe_structure">
<div class="container">
<h3 t-field="person.name"/>
<p>Last modified: <i t-field="person.write_date" t-options='{"format": "long"}'/></p>
<div t-field="person.biography"/>
</div>
</div>
або відносний дисплей:
academy/templates.xml
¶<div class="oe_structure">
<div class="container">
<h3 t-field="person.name"/>
<p>Last modified: <i t-field="person.write_date" t-options='{"widget": "relative"}'/></p>
<div t-field="person.biography"/>
</div>
</div>
Адміністрування та інтеграція ERP¶
Короткий і неповний вступ до адміністрування Odoo¶
Адміністрацію Odoo ненадовго побачили під час розділу підтримка сайту. Ми можемо повернутися до нього за допомогою у меню (або Увійти, якщо ви вийшли).
Концептуальна структура бекенда Odoo проста:
першими є меню, дерево (меню можуть мати підменю) записів. Меню без дітей відображаються на…
дії. Дії мають різні типи: посилання, звіти, код, який повинен виконати Odoo, або відображення даних. Дії відображення даних називаються дії вікна, вони вказують Odoo відобразити дану модель відповідно до набору представлень…
подання має тип, широку категорію, якій воно відповідає (список, графік, календар) і архітектуру, яка налаштовує спосіб відображення моделі в поданні.
Редагування в адміністрації Odoo¶
За замовчуванням модель Odoo практично невидима для користувача. Щоб зробити його видимим, він має бути доступним через дію, яка сама має бути доступною, як правило, через меню.
Давайте створимо меню для нашої моделі:
academy/__manifest__.py
¶# always loaded
'data': [
'security/ir.model.access.csv',
'templates.xml',
'views.xml',
],
academy/views.xml
¶<odoo>
<record id="action_academy_teachers" model="ir.actions.act_window">
<field name="name">Academy teachers</field>
<field name="res_model">academy.teachers</field>
</record>
<menuitem sequence="0" id="menu_academy" name="Academy"/>
<menuitem id="menu_academy_content" parent="menu_academy"
name="Academy Content"/>
<menuitem id="menu_academy_content_teachers"
parent="menu_academy_content"
action="action_academy_teachers"/>
</odoo>
тоді доступ до http://localhost:8069/web/ у верхньому лівому куті має бути меню Академія, яке вибрано за замовчуванням, оскільки це перше меню, і відкривши список викладачів. Зі списку можна Створити нові записи вчителя та перейти до представлення «форми» за записами.
If there is no definition of how to present records (a
view) Odoo will automatically create a basic one
on-the-fly. In our case it works for the «list» view for now (only displays
the teacher’s name) but in the «form» view the HTML biography
field is
displayed side-by-side with the name
field and not given enough space.
Let’s define a custom form view to make viewing and editing teacher records
a better experience:
academy/views.xml
¶<record id="academy_teacher_form" model="ir.ui.view">
<field name="name">Academy teachers: form</field>
<field name="model">academy.teachers</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="name"/>
<field name="biography"/>
</sheet>
</form>
</field>
</record>
Відносини між моделями¶
Ми бачили пару «базових» полів, які зберігаються безпосередньо в записі. Існує кілька основних полів. Другою широкою категорією полів є зв’язки, які використовуються для зв’язування записів один з одним (у межах моделі або між моделями).
Для демонстрації давайте створимо модель курсів. Кожен курс має мати поле teacher
із посиланням на один запис викладача, але кожен викладач може викладати багато курсів:
academy/models.py
¶class Courses(models.Model):
_name = 'academy.courses'
name = fields.Char()
teacher_id = fields.Many2one('academy.teachers', string="Teacher")
academy/security/ir.model.access.csv
¶id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0
access_academy_courses,access_academy_courses,model_academy_courses,,1,0,0,0
давайте також додамо представлення, щоб ми могли бачити та редагувати викладача курсу:
academy/views.xml
¶<record id="action_academy_courses" model="ir.actions.act_window">
<field name="name">Academy courses</field>
<field name="res_model">academy.courses</field>
</record>
<record id="academy_course_search" model="ir.ui.view">
<field name="name">Academy courses: search</field>
<field name="model">academy.courses</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="teacher_id"/>
</search>
</field>
</record>
<record id="academy_course_list" model="ir.ui.view">
<field name="name">Academy courses: list</field>
<field name="model">academy.courses</field>
<field name="arch" type="xml">
<tree string="Courses">
<field name="name"/>
<field name="teacher_id"/>
</tree>
</field>
</record>
<record id="academy_course_form" model="ir.ui.view">
<field name="name">Academy courses: form</field>
<field name="model">academy.courses</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="name"/>
<field name="teacher_id"/>
</sheet>
</form>
</field>
</record>
<menuitem sequence="0" id="menu_academy" name="Academy"/>
<menuitem id="menu_academy_content" parent="menu_academy"
name="Academy Content"/>
<menuitem id="menu_academy_content_courses"
parent="menu_academy_content"
action="action_academy_courses"/>
<menuitem id="menu_academy_content_teachers"
parent="menu_academy_content"
action="action_academy_teachers"/>
Також має бути можливість створювати нові курси безпосередньо зі сторінки викладача або переглядати всі курси, які він викладає, тому додайте обернений зв’язок
до моделі teachers:
academy/models.py
¶class Teachers(models.Model):
_name = 'academy.teachers'
name = fields.Char()
biography = fields.Html()
course_ids = fields.One2many('academy.courses', 'teacher_id', string="Courses")
class Courses(models.Model):
_name = 'academy.courses'
name = fields.Char()
teacher_id = fields.Many2one('academy.teachers', string="Teacher")
academy/views.xml
¶<record id="academy_teacher_form" model="ir.ui.view">
<field name="name">Academy teachers: form</field>
<field name="model">academy.teachers</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="name"/>
<field name="biography"/>
<field name="course_ids">
<tree Sstring="Courses" editable="bottom">
<field name="name"/>
</tree>
</field>
</sheet>
</form>
</field>
</record>
Обговорення та повідомлення¶
Odoo надає технічні моделі, які безпосередньо не відповідають бізнес-потребам, але додають можливості бізнес-об’єктам без необхідності створювати їх вручну.
Однією з них є система Chatter, частина системи електронної пошти та обміну повідомленнями Odoo, яка може додавати сповіщення та теми обговорень до будь-якої моделі. Модель просто має _inherit
mail.thread
і додати поле message_ids
до свого представлення форми, щоб відобразити потік обговорення. Теми обговорень створюються для кожного запису.
Для нашої academy має сенс дозволити обговорювати курси, щоб, напр. планування змін або обговорення між викладачами та асистентами:
academy/__manifest__.py
¶'version': '0.1',
# any module necessary for this one to work correctly
'depends': ['website', 'mail'],
# always loaded
'data': [
academy/models.py
¶class Courses(models.Model):
_name = 'academy.courses'
_inherit = 'mail.thread'
name = fields.Char()
teacher_id = fields.Many2one('academy.teachers', string="Teacher")
academy/views.xml
¶<record id="academy_course_form" model="ir.ui.view">
<field name="name">Academy courses: form</field>
<field name="model">academy.courses</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="name"/>
<field name="teacher_id"/>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
У нижній частині кожної форми курсу тепер є ланцюжок обговорень і можливість для користувачів системи залишати повідомлення та стежити за обговореннями, пов’язаними з конкретними курсами, або відмовлятися від них.
Продаж курсів¶
Odoo також надає бізнес-моделі, які дозволяють більш безпосередньо використовувати або вибирати потреби бізнесу. Наприклад, модуль website_sale
налаштовує сайт ел. комерції на основі продуктів у системі Odoo. Ми можемо легко зробити підписки на курси доступними для продажу, зробивши наші курси окремими продуктами.
Замість попереднього класичного успадкування це означає заміну нашої моделі курсу моделлю продукту та розширення продуктів на місці (щоб додати до них все, що нам потрібно).
Перш за все нам потрібно додати залежність від website_sale
, щоб ми отримували як продукти (через sale
), так і інтерфейс ел. комерції:
academy/__manifest__.py
¶'version': '0.1',
# any module necessary for this one to work correctly
'depends': ['mail', 'website_sale'],
# always loaded
'data': [
перезапустіть Odoo, оновіть свій модуль, тепер на веб-сайті є розділ Магазин, у якому перераховано декілька попередньо заповнених (через демонстраційні дані) продуктів.
Другим кроком є заміна моделі courses на product.template
і додавання нової категорії продукту для курсів:
academy/__manifest__.py
¶ 'security/ir.model.access.csv',
'templates.xml',
'views.xml',
'data.xml',
],
# only loaded in demonstration mode
'demo': [
academy/data.xml
¶<odoo>
<record model="product.public.category" id="category_courses">
<field name="name">Courses</field>
<field name="parent_id" ref="website_sale.categ_others"/>
</record>
</odoo>
academy/demo.xml
¶<record id="course0" model="product.template">
<field name="name">Course 0</field>
<field name="teacher_id" ref="padilla"/>
<field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
<field name="website_published">True</field>
<field name="list_price" type="float">0</field>
<field name="type">service</field>
</record>
<record id="course1" model="product.template">
<field name="name">Course 1</field>
<field name="teacher_id" ref="padilla"/>
<field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
<field name="website_published">True</field>
<field name="list_price" type="float">0</field>
<field name="type">service</field>
</record>
<record id="course2" model="product.template">
<field name="name">Course 2</field>
<field name="teacher_id" ref="vaughn"/>
<field name="public_categ_ids" eval="[(4, ref('academy.category_courses'), False)]"/>
<field name="website_published">True</field>
<field name="list_price" type="float">0</field>
<field name="type">service</field>
</record>
academy/models.py
¶class Courses(models.Model):
_name = 'academy.courses'
_inherit = ['mail.thread', 'product.template']
name = fields.Char()
teacher_id = fields.Many2one('academy.teachers', string="Teacher")
З його встановленням кілька курсів тепер доступні в Магазин, хоча їх, можливо, доведеться пошукати.
Примітка
щоб розширити модель на місці, вона
успадкована
без надання їй нового_name
product.template
вже використовує систему обговорень, тому ми можемо видалити його з нашої моделі розширеннями створюємо наші курси як опубліковані за замовчуванням, щоб їх можна було переглядати без входу в систему
Зміна існуючих представлень¶
Наразі ми коротко бачили:
створення нових моделей
створення нових представлень
створення нових записів
зміна існуючих моделей
Нам залишається зміна існуючих записів і зміна існуючих представлень. Ми зробимо обидва на сторінках Магазин.
Зміна подання здійснюється шляхом створення подання розширення, яке застосовується поверх вихідного подання та змінює його. Ці представлення змін можна додавати або видаляти, не змінюючи оригінал, що полегшує випробування та відкат змін.
Оскільки наші курси безкоштовні, немає причин відображати їхню ціну на сторінці магазину, тому ми збираємося змінити представлення і приховати ціну, якщо вона дорівнює 0. Перше завдання - з’ясувати, у якому вікні відображається ціна, це може можна зробити за допомогою
, який дозволяє нам читати різні шаблони, задіяні у відтворенні сторінки. Переглянувши кілька з них, видається, що «Елемент продукту» є ймовірною причиною.Зміна архітектури представлення виконується в 3 кроки:
Створити нове представлення
Розширте представлення для зміни, встановивши
inherit_id
нового подання на зовнішній ідентифікатор зміненого представленняВ архітектурі використовуйте тег
xpath
, щоб вибрати та змінити елементи зі зміненого представлення
academy/templates.xml
¶ <template id="product_item_hide_no_price" inherit_id="website_sale.products_item">
<xpath expr="//div[hasclass('product_price')]/b" position="attributes">
<attribute name="t-if">product.price > 0</attribute>
</xpath>
</template>
Друге, що ми змінимо, це зробити бокову панель категорій продуктів видимою за замовчуванням:
дозволяє вмикати та вимикати дерево категорій продуктів (використовується для фільтрації основного дисплея).Це робиться за допомогою полів customize_show
і active
шаблонів розширень: шаблон розширення (наприклад, той, який ми щойно створили) може бути customize_show=True. Цей вибір відобразить представлення у меню Налаштувати з прапорцем, що дозволить адміністраторам активувати або вимикати їх (і легко налаштовувати сторінки свого веб-сайту).
Нам просто потрібно змінити запис Категорії продукта і встановити для нього значення active=»True»:
academy/templates.xml
¶<record id="website_sale.products_categories" model="ir.ui.view">
<field name="active" eval="True"/>
</record>
Завдяки цьому бічна панель Категорії продуктів буде автоматично ввімкнена, коли встановлено модуль Academy.