[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:
commit
fd008435e0
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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('/')
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import ir_actions
|
||||
import ir_ui_view
|
||||
import website
|
||||
import ir_qweb
|
||||
|
|
|
@ -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
|
|
@ -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>
|
Loading…
Reference in New Issue