Первые веб страницы на odoo
Содержание
В этой статье мы рассмотрим, какие базовые абстракции использует Odoo для формирования веб страниц. Эта статья(и последующие из раздела посвященного сайту) не является учебником по всем возможностям современного сайтостроения, пример будет специально упрощен и сфокусирован на характерных исключительно для Odoo тонкостях. Тем не менее, поскольку сам учебник рассчитан на совсем новичков я постараюсь разъяснить каждый аспект того, что происходит.
Подготовка
Для того, чтобы использовать следующий пример, вам необходимо переключить текущий разрабатываемый проект на другую ветку.
Вот ее имя - 16.0-webpage-example
Затем удалите текущую базу и создайте новую.
Убедитесь, что у вас не осталось вкладок со старыми сессиями
В файл конфигурации в параметры init_modules
и update_modules
добавьте имя модуля first_module_public_page
Запустите менеджер с параметрами -d
, -i
, и -u
Перейдите откройте браузер по адресу http://127.0.0.1:8069/records/
Контроллеры
О том что такое контроллеры, можно почерпнуть из документации
У нас есть контроллеры, которые могут ответить на http запрос, который поступает к нашему экземпляру odoo. Контроллер это функция, которая обрабатывает http запрос направленный на конкретный URI на нашем сервере. Для того, чтобы указать какой именно URI, а так же метод запроса и другие параметры, необходимо задекорировать нашу функцию декоратором http.route:
- Декоратор
http.route
. Связывает указанные URI в первом параметре и функцию-обработчик, которой и является декорируемая функция. Параметры функции-декоратора можно увидеть здесь - Декорируемая функция - обработчик запроса. Внутри нее происходит вся работа для формирования ответа на запрос
- Пример осуществления доступа к записям моделей. Обратите внимание, что доступ к объекту окружения
env
осуществляется не черезself
а с использованием импортируемого объектаrequest
- Обычный python словарь, который содержит значения для генерации(рендеринга) html строки, на базе Qweb шаблона. Ключи словаря будут доступны внутри шаблона как переменные
- В качестве результат работы функции здесь указан
html
, который в свою очередь генерируется с помощью указанного поxml_id
шаблона и ранее описанного словаря значений
Как сгенерировать HTML
- Функция
request.render
выполняет формирование html на основании шаблона сxml_id
first_module_public_page.first_model_public_list
и передает туда словарь со значениямиvalues
- Внутри шаблона вызывается шаблон
xml_id
first_module_public_page.base_layout
, который по факту будет являться нашим родителем и представляет из себя упрощенную разметку html страницы. Красным цветом выделена директива, которая указывает где будет вставлен вызывающий его шаблон. - Для того, чтобы отобразить весь список доступных записей, мы с помощью директивы
t-foreach
(внимательно смотрите официальную документацию) начинаем итерировать объект с именемall_records
и присваиваем для переменной хранящей в себе объект шага итерацииrecord
. Как мы можем видетьall_records
стал нам доступен после того, как мы добавили его в словарьvalues
и передали в качестве аргумента функцииrequest.render
- Если пользователь на первой странице нажмет на ссылку с записью браузер отправит запрос на указанный контроллер. Обратите внимание на то, как контроллером будет интерпретироваться числа стоящее после
/records/
. Любое число, находящееся в этомuri
будет интерпретировано как значение поляid
моделиfirst.model
и найденный рекордсет из одной записи будет передан в функцию обработчик как аргумент с указанным именем, в нашем случае это имя будетfirst_model_record_id
. Так же обратите внимание на параметрauth=user
, это говорит о том, что функция обработчик контроллера будет вызвана только для аутентифицированных пользователей, для гостей будет предложено ввести свой логин и пароль. - Мы опять вызываем функцию
request.render
в которой указываем имя шаблона сxml_id
first_module_public_page.first_model_public_item
и словарем со значениямиvalues
- Вызов родительского шаблона
xml_id
first_module_public_page.base_layout
- Использование объекта
record
из ранее созданного словаря значенийvalues
. Здесь мы просто обращаемся к атрибутам записи так же как и в кодеpython
Давайте теперь рассмотрим пример обработки одного запроса, но уже так, как его видит браузер:
- Отравляем запрос на сервер
- Видим HTML код, который нам прислал сервер и то, как его интерпретировал браузер в виде веб страницы.
Использование ассетов
Как вы уже могли заметить наша веб страница выглядит весьма аскетично для современного веба, но на данном этапе это было сделано намеренно для упрощения финально конструкции. Тем не менее в нашем примере вы так же найдете способы подключения css, js и других файлов, которые вам могут понадобится для построения вашей веб страницы. Собственно эти файлы и называются ассетами.
Начиная с версии 15.0 Odoo требует объявления ассетов в __manifest__.py
файле по ключу assets
:
Как мы можем видеть, что в файле __manifest__.py
мы сами придумали xml_id
для нашего набора или бандла ассетов и затем применили его в шаблоне базовой страницы, который наследуют все остальные шаблоны. Обратите внимание что путь к файлам ассетов начинается с имени модуля. В шаблоне вы так же можете увидеть использование директив t-js="false"
и t-css="false"
, они говорят что один бандл не содержит в себе css
, а второй не содержит js
файлов.
Безопасность
Необходимо так же сказать пару слов о механизмах безопасности, которые используются при создании веб страниц. Если вы внимательно читали предыдущий материал, то могли заметить, что ранее уже упоминался механизм, который позволяет сделать список записей доступными для не аутентифицированных пользователей, а при переходе внутрь записи, вам уже нужно ввести логин и пароль. Как это реализовано в текущем примере:
- Для начала я дал группе пользователей с
xml_id
base.group_public
права на чтение моделиfirst.model
. Вы можете увидеть это здесь - Все не аутентифицированные запросы попадающие на контроллер с параметром
auth="public"
автоматически присваиваются анонимному пользователю, который и входит в группуbase.group_public
. Таким образом при обращении к моделям и их записям автоматически будет применяться полный механизм безопасности Odoo. Да, конечно, вы можете использоватьsudo()
при работе из контроллера, но его использование необходимо максимально ограничить, т.к. с развитием проекта вы рискуете просто упустить из виду бреши в безопасности из-за роста кодовой базы и количества бесконтрольных обращений к системе. - В случае же, если вам нужно скрыть страницу исключительно для аутентифицированных пользователей, вы в контроллере должны применять параметр
auth="user"
, что автоматически вызовет проверку того, аутентифицирован ли пользователь на сайте или нет. И все обращения к ресурсам системы внутри контроллера уже будут авторизованы от его имени.
Обсуждение
Обсудить, указать на ошибки и опечатки можно здесь