[MERGE] [ADD] website: added support for calling a server action through a new controller, allowing to build website pages through server action.

website: added website/action/<id_or_xml_id> route, that runs the server action designed by its id or xml_id. Only published code server action are run. If the server action returns a response (for example the result of a template rendering), it is returned as result of the controller. This allows to have server action returning a rendered template, to display custom website pages based on some computation.

website: added an override of ir_actions_server:
- added website_published field: only published server action can be run + view update
- evaluation context gets request for evaluation, to enable request.render(template) or request.params.get(key) in order to retrieve the result of a form
- code server action returns 'response' the same way 'action' can be returned for classic code server action

bzr revid: tde@openerp.com-20140206083923-3ealsxehyicr2la1
This commit is contained in:
Thibault Delavallée 2014-02-06 09:39:23 +01:00
commit fd008435e0
6 changed files with 205 additions and 3 deletions

View File

@ -20,12 +20,13 @@ OpenERP Website CMS
'views/snippets.xml',
'views/themes.xml',
'views/res_config.xml',
'views/ir_actions.xml',
],
'demo': [
'data/website_demo.xml',
],
'js': ['static/src/js/website.backend.js'],
'qweb' : ['static/src/xml/website.backend.xml'],
'qweb': ['static/src/xml/website.backend.xml'],
'css': ['static/src/css/website.backend.css'],
'application': True,
}

View File

@ -9,7 +9,6 @@ import datetime
from sys import maxint
import psycopg2
import werkzeug
import werkzeug.exceptions
import werkzeug.utils
@ -27,6 +26,7 @@ logger = logging.getLogger(__name__)
# Completely arbitrary limits
MAX_IMAGE_WIDTH, MAX_IMAGE_HEIGHT = IMAGE_LIMITS = (1024, 768)
class Website(openerp.addons.web.controllers.main.Home):
#------------------------------------------------------
# View
@ -366,5 +366,34 @@ class Website(openerp.addons.web.controllers.main.Home):
return response
#------------------------------------------------------
# Server actions
#------------------------------------------------------
@http.route(['/website/action/<id_or_xml_id>'], type='http', auth="public", website=True)
def actions_server(self, id_or_xml_id, **post):
cr, uid, context = request.cr, request.uid, request.context
res, action_id, action = None, None, None
ServerActions = request.registry['ir.actions.server']
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
# find the action_id, either an int, an int into a basestring, or an xml_id
if isinstance(id_or_xml_id, basestring) and '.' in id_or_xml_id:
action_id = request.registry['ir.model.data'].xmlid_to_res_id(request.cr, request.uid, id_or_xml_id, raise_if_not_found=False)
else:
try:
action_id = int(id_or_xml_id)
except ValueError:
pass
# check it effectively exists
if action_id:
action_ids = ServerActions.exists(cr, uid, [action_id], context=context)
action_id = action_ids and action_ids[0] or None
# run it, return only LazyResponse that are templates to be rendered
if action_id:
action = ServerActions.browse(cr, uid, action_id, context=context)
if action.state == 'code' and action.website_published:
action_res = ServerActions.run(cr, uid, [action_id], context=context)
if isinstance(action_res, LazyResponse):
res = action_res
if res:
return res
return request.redirect('/')

View File

@ -13,4 +13,122 @@
<field name="rml_header1">Great Product for Great People</field>
</record>
</data>
<data noupdate="1">
<!--
Some demo data for front-end server action generating templates
-->
<template id="template_partner_post" name="Partner Post and Thanks (Website Server Action Demo)">
<t t-call="website.layout">
<t t-set="additional_title">Partner Detail</t>
<div id="wrap">
<div class="oe_structure">
<section data-snippet-id="title">
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Thank you for posting a message !</h2>
</div>
</div>
</div>
</section>
</div>
</div>
</t>
</template>
<record id="action_partner_post" model="ir.actions.server">
<field name="name">Website Partner Post and Thanks Demo</field>
<field name="condition">True</field>
<field name="website_published" eval="True"/>
<field name="model_id" ref="base.model_res_partner"/>
<field name="code">
partner_id, partner = False, None
post_partner_id = request.params.get('partner_id')
post_body = request.params.get('body')
if post_partner_id:
try:
post_partner_id = int(post_partner_id)
except:
post_partner_id = False
if post_partner_id:
partner_ids = pool['res.partner'].search(cr, uid, [('id', '=', post_partner_id)], context=context)
partner_id = partner_ids and partner_ids[0] or False
if partner_id and post_body:
partner = pool['res.partner'].message_post(cr, uid, partner_id, body=post_body, subtype='mail.mt_comment', context=context)
values = {
'partner': partner,
}
response = request.website.render("website.template_partner_post", values)
</field>
<field name="state">code</field>
<field name="type">ir.actions.server</field>
</record>
<template id="template_partner_comment" name="Partner Comment (Website Server Action Demo)">
<t t-call="website.layout">
<t t-set="additional_title">Partners</t>
<div id="wrap">
<div class="oe_structure">
<section data-snippet-id="title">
<div class="container">
<div class="row">
<div class="col-md-12">
<h1 class="text-center">Send a Message to our Partners</h1>
<h3 class="text-muted text-center">Discuss and Comments</h3>
</div>
</div>
</div>
</section>
</div>
<div class="container">
<div class="row">
<form class="form-horizontal" action="/website/action/website.action_partner_post" method="post">
<div class="form-group">
<label class="col-sm-2 control-label">Recipient</label>
<div class="col-sm-10">
<select t-if="partners" name="partner_id" class="form-control">
<t t-foreach="partners" t-as="partner"><option t-att-value="partner.id" t-esc="partner.name"/></t>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Message</label>
<div class="col-sm-10">
<textarea name="body" rows="10" class="form-control"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default btn-primary">
Send <span class="fa fa-long-arrow-right"/>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</t>
</template>
<record id="action_partner_comment" model="ir.actions.server">
<field name="name">Website Partners Comment Form</field>
<field name="condition">True</field>
<field name="website_published" eval="True"/>
<field name="model_id" ref="base.model_res_partner"/>
<field name="code">
partner_ids = pool['res.partner'].search(cr, uid, [('customer', '=', True)], context=context)
partners = pool['res.partner'].browse(cr, uid, partner_ids, context=context)
values = {
'partners': partners,
}
response = request.website.render("website.template_partner_comment", values)
</field>
<field name="state">code</field>
<field name="type">ir.actions.server</field>
</record>
</data>
</openerp>

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import ir_actions
import ir_ui_view
import website
import ir_qweb

View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
from openerp.addons.web.http import request
from openerp.osv import fields, osv
class actions_server(osv.Model):
""" Add website option in server actions. """
_name = 'ir.actions.server'
_inherit = ['ir.actions.server']
_columns = {
'website_published': fields.boolean(
'Available on the Website',
help='A code server action can be executed from the website, using a dedicated'
'controller. The address is <base>/website/action/<id_or_xml_id>.'
'Set this field as True to allow users to run this action. If it'
'set to is False the action cannot be run through the website.'),
}
def _get_eval_context(self, cr, uid, action, context=None):
""" Override to add the request object in eval_context. """
eval_context = super(actions_server, self)._get_eval_context(cr, uid, action, context=context)
if action.state == 'code':
eval_context['request'] = request
return eval_context
def run_action_code_multi(self, cr, uid, action, eval_context=None, context=None):
""" Override to allow returning response the same way action is already
returned by the basic server action behavior. Note that response has
priority over action, avoid using both. """
res = super(actions_server, self).run_action_code_multi(cr, uid, action, eval_context, context)
if 'response' in eval_context:
return eval_context['response']
return res

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_server_action_form_website">
<field name="name">ir.actions.server.form.website</field>
<field name="model">ir.actions.server</field>
<field name="inherit_id" ref="base.view_server_action_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='state']" position="after">
<field name="website_published"
attrs="{'invisible': [('state', '!=', 'code')]}"/>
</xpath>
</field>
</record>
</data>
</openerp>