[ADD] Helper for /website/image (allows to use aggressive cache)
This commit is contained in:
parent
cdcd488f5a
commit
bc5e6fa2cb
|
@ -8,8 +8,6 @@ import xml.etree.ElementTree as ET
|
|||
import logging
|
||||
import re
|
||||
|
||||
from sys import maxint
|
||||
|
||||
import werkzeug.utils
|
||||
import urllib2
|
||||
import werkzeug.wrappers
|
||||
|
@ -17,7 +15,7 @@ from PIL import Image
|
|||
|
||||
import openerp
|
||||
from openerp.addons.web import http
|
||||
from openerp.http import request, Response
|
||||
from openerp.http import request, STATIC_CACHE
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -397,8 +395,8 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
|
||||
@http.route([
|
||||
'/website/image',
|
||||
'/website/image/<model>/<id>/<field>',
|
||||
'/website/image/<model>/<id>/<field>/<int:max_width>x<int:max_height>'
|
||||
'/website/image/<model>-<id>-<field>',
|
||||
'/website/image/<model>-<id>-<field>-<int:max_width>x<int:max_height>'
|
||||
], auth="public", website=True)
|
||||
def website_image(self, model, id, field, max_width=None, max_height=None):
|
||||
""" Fetches the requested field and ensures it does not go above
|
||||
|
@ -416,9 +414,12 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
all cases.
|
||||
"""
|
||||
try:
|
||||
idsha = id.split('_')
|
||||
id = idsha[0]
|
||||
response = werkzeug.wrappers.Response()
|
||||
return request.registry['website']._image(
|
||||
request.cr, request.uid, model, id, field, response, max_width, max_height)
|
||||
request.cr, request.uid, model, id, field, response, max_width, max_height,
|
||||
cache=STATIC_CACHE if len(idsha) > 1 else None)
|
||||
except Exception:
|
||||
logger.exception("Cannot render image field %r of record %s[%s] at size(%s,%s)",
|
||||
field, model, id, max_width, max_height)
|
||||
|
|
|
@ -286,21 +286,17 @@ class Image(orm.AbstractModel):
|
|||
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
|
||||
if options is None: options = {}
|
||||
classes = ['img', 'img-responsive'] + options.get('class', '').split()
|
||||
aclasses = ['img', 'img-responsive'] + options.get('class', '').split()
|
||||
classes = ' '.join(itertools.imap(escape, aclasses))
|
||||
|
||||
url_frags = {
|
||||
'classes': ' '.join(itertools.imap(escape, classes)),
|
||||
'model': record._model._name,
|
||||
'id': record.id,
|
||||
'field': field_name,
|
||||
'max_size': '',
|
||||
}
|
||||
max_size = None
|
||||
max_width, max_height = options.get('max_width', 0), options.get('max_height', 0)
|
||||
if max_width or max_height:
|
||||
url_frags['max_size'] = '/%sx%s' % (max_width, max_height)
|
||||
max_size = '%sx%s' % (max_width, max_height)
|
||||
|
||||
img = '<img class="%(classes)s" src="/website/image/%(model)s/%(id)s/%(field)s%(max_size)s"/>'
|
||||
return ir_qweb.HTMLSafe(img % url_frags)
|
||||
src = self.pool['website'].image_url(cr, uid, record, field_name, max_size)
|
||||
img = '<img class="%s" src="%s"/>' % (classes, src)
|
||||
return ir_qweb.HTMLSafe(img)
|
||||
|
||||
local_url_re = re.compile(r'^/(?P<module>[^]]+)/static/(?P<rest>.+)$')
|
||||
def from_html(self, cr, uid, model, column, element, context=None):
|
||||
|
|
|
@ -4,13 +4,13 @@ import contextlib
|
|||
import datetime
|
||||
import hashlib
|
||||
import inspect
|
||||
import itertools
|
||||
import logging
|
||||
import math
|
||||
import mimetypes
|
||||
import unicodedata
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import urlparse
|
||||
|
||||
from PIL import Image
|
||||
|
@ -513,7 +513,7 @@ class website(osv.osv):
|
|||
response.data = f.read()
|
||||
return response.make_conditional(request.httprequest)
|
||||
|
||||
def _image(self, cr, uid, model, id, field, response, max_width=maxint, max_height=maxint, context=None):
|
||||
def _image(self, cr, uid, model, id, field, response, max_width=maxint, max_height=maxint, cache=None, context=None):
|
||||
""" Fetches the requested field and ensures it does not go above
|
||||
(max_width, max_height), resizing it if necessary.
|
||||
|
||||
|
@ -565,6 +565,10 @@ class website(osv.osv):
|
|||
response.set_etag(hashlib.sha1(record[field]).hexdigest())
|
||||
response.make_conditional(request.httprequest)
|
||||
|
||||
if cache:
|
||||
response.cache_control.max_age = cache
|
||||
response.expires = int(time.time() + cache)
|
||||
|
||||
# conditional request match
|
||||
if response.status_code == 304:
|
||||
return response
|
||||
|
@ -593,6 +597,13 @@ class website(osv.osv):
|
|||
|
||||
return response
|
||||
|
||||
def image_url(self, cr, uid, record, field, size=None, context=None):
|
||||
"""Returns a local url that points to the image field of a given browse record."""
|
||||
model = record._name
|
||||
id = '%s_%s' % (record.id, hashlib.sha1(record.write_date).hexdigest()[0:7])
|
||||
size = '' if size is None else '-%s' % size
|
||||
return '/website/image/%s-%s-%s%s' % (model, id, field, size)
|
||||
|
||||
|
||||
class website_menu(osv.osv):
|
||||
_name = "website.menu"
|
||||
|
@ -668,11 +679,7 @@ class ir_attachment(osv.osv):
|
|||
if attach.url:
|
||||
result[attach.id] = attach.url
|
||||
else:
|
||||
result[attach.id] = urlplus('/website/image', {
|
||||
'model': 'ir.attachment',
|
||||
'field': 'datas',
|
||||
'id': attach.id
|
||||
})
|
||||
result[attach.id] = self.pool['website'].image_url(cr, uid, attach, 'datas')
|
||||
return result
|
||||
def _datas_checksum(self, cr, uid, ids, name, arg, context=None):
|
||||
return dict(
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
<div t-foreach="blog_posts" t-as="blog_post" class="mb32">
|
||||
|
||||
<img class="img-circle pull-right mt16"
|
||||
t-attf-src="/website/image/res.partner/{{ blog_post.author_id.id }}/image_small"
|
||||
t-att-src="website.image_url(blog_post.author_id, 'image_small')"
|
||||
style="width: 50px;"/>
|
||||
|
||||
<a t-attf-href="/blog/#{ slug(blog_post.blog_id) }/post/#{ slug(blog_post) }">
|
||||
|
@ -205,7 +205,7 @@
|
|||
<h2 t-field="blog_post.subtitle"/>
|
||||
<p class="post-meta text-muted text-center" name="blog_post_data"/>
|
||||
<div>
|
||||
<img class="img-circle" t-attf-src="/website/image/res.partner/{{ blog_post.author_id.id }}/image_small" style="width: 30px; margin-right: 10px;"/>
|
||||
<img class="img-circle" t-att-src="website.image_url(blog_post.author_id, 'image_small')" style="width: 30px; margin-right: 10px;"/>
|
||||
<span t-field="blog_post.author_id" style="display: inline-block;" t-field-options='{
|
||||
"widget": "contact",
|
||||
"fields": ["name"]
|
||||
|
@ -224,7 +224,7 @@
|
|||
<ul class="media-list" id="comments-list">
|
||||
<li t-foreach="comments" t-as="message" class="media">
|
||||
<span class="pull-left">
|
||||
<img class="media-object img img-circle" t-attf-src="/website/image/mail.message/{{ message.id }}/author_avatar" style="width: 30px"/>
|
||||
<img class="media-object img img-circle" t-att-src="website.image_url(message, 'author_avatar')" style="width: 30px"/>
|
||||
</span>
|
||||
<div class="media-body">
|
||||
<t t-call="website.publish_short">
|
||||
|
@ -249,7 +249,7 @@
|
|||
<h1 t-field="next_post.name"/>
|
||||
<h2 t-field="next_post.subtitle"/>
|
||||
<div>
|
||||
<img class="img-circle" t-attf-src="'/website/image/res.partner/{{ next_post.author_id.id }}/image_small" style="width: 30px; margin-right: 10px;"/>
|
||||
<img class="img-circle" t-att-src="website.image_url(next_post.author_id, 'image_small')" style="width: 30px; margin-right: 10px;"/>
|
||||
<span t-field="next_post.author_id" style="display: inline-block;" t-field-options='{
|
||||
"widget": "contact",
|
||||
"fields": ["name"]
|
||||
|
@ -292,7 +292,7 @@
|
|||
<form id="comment" t-attf-action="/blogpost/comment" method="POST">
|
||||
<div class="media">
|
||||
<span class="pull-left">
|
||||
<img class="img img-circle media-object" t-attf-src="/website/image/res.partner/{{ user_id.partner_id.id }}/image_small" style="width: 30px"/>
|
||||
<img class="img img-circle media-object" t-att-src="website.image_url(user_id.partner_id, 'image_small')" style="width: 30px"/>
|
||||
</span>
|
||||
<div class="media-body">
|
||||
<input name="blog_post_id" t-att-value="blog_post.id" type="hidden"/>
|
||||
|
|
|
@ -404,7 +404,7 @@
|
|||
<div class="country_events_list">
|
||||
<div>
|
||||
<t t-if="country">
|
||||
<img class="img-rounded img-responsive" t-attf-src="/website/image/res.country/{{ country.id }}/image"></img>
|
||||
<img class="img-rounded img-responsive" t-att-src="website.image_url(country, 'image')"></img>
|
||||
<h4><b>Events: <span t-esc="country.name"></span></b></h4>
|
||||
</t>
|
||||
<t t-if="not country">
|
||||
|
|
|
@ -12,6 +12,3 @@ class hr(osv.osv):
|
|||
_defaults = {
|
||||
'website_published': False
|
||||
}
|
||||
|
||||
def img(self, cr, uid, ids, field='image_small', context=None):
|
||||
return "/website/image/%s/%s/%s" % (self._name, ids[0], field)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<div t-foreach="employee_ids" t-as="employee" class="col-sm-3 col-lg-2 mt16 text-center colsize">
|
||||
<t t-call="website.publish_management"><t t-set="object" t-value="employee"/></t>
|
||||
<div class="clearfix"/>
|
||||
<img t-att-src="employee.img('image_medium')" class="img shadow img-rounded"/>
|
||||
<img t-att-src="website.image_url(employee, 'image_medium')" class="img shadow img-rounded"/>
|
||||
<div class="mt8">
|
||||
<strong t-field="employee.name"></strong>
|
||||
</div>
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
</div>
|
||||
<div class="row mt8" t-foreach="groups" t-as="group">
|
||||
<div class="col-md-3">
|
||||
<img t-attf-src="/website/image/mail.group/{{ group['id'] }}/image_small" class="pull-left"/>
|
||||
<img t-att-src="website.image_url(group, 'image_small')" class="pull-left"/>
|
||||
<strong><a t-attf-href="/groups/#{ slug(group) }" t-esc="group.name"/></strong><br />
|
||||
<t t-if="group.alias_id and group.alias_id.alias_name and group.alias_id.alias_domain">
|
||||
<i class='fa fa-envelope-o'/>
|
||||
|
@ -177,7 +177,7 @@
|
|||
</div>
|
||||
<div class="media">
|
||||
<img class="img-rounded pull-left mt0 media-object o_mg_avatar"
|
||||
t-attf-src="/website/image/mail.message/{{ message.id }}/author_avatar"/>
|
||||
t-att-src="website.image_url(message, 'author_avatar')"/>
|
||||
<div class="media-body">
|
||||
<h4 class="media-heading" t-esc="message.description"/>
|
||||
<small>
|
||||
|
@ -247,7 +247,7 @@
|
|||
<ul class="media-list">
|
||||
<li t-foreach="messages" t-as="thread" class="media">
|
||||
<img class="img-rounded pull-left mt0 media-object o_mg_avatar"
|
||||
t-attf-src="/website/image/mail.message/{{ thread.id }}/author_avatar"/>
|
||||
t-att-src="website.image_url(thread, 'author_avatar')"/>
|
||||
<div class="media-body">
|
||||
<h4 class="media-heading">
|
||||
<a t-attf-href="/groups/#{slug(group)}/#{slug(thread)}?mode=#{mode}&date_begin=#{date_begin}&date_end=#{date_end}" t-esc="thread.description"/>
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
<t t-foreach="quotation.message_ids" t-as="message">
|
||||
<li class="media" t-if="message.type <> 'comment' or message.subtype_id">
|
||||
<div class="media-body">
|
||||
<img class="media-object pull-left" t-attf-src="/website/image/res.partner/{{ message.author_id.id }}/image_small" style="width: 50px; margin-right: 10px;"/>
|
||||
<img class="media-object pull-left" t-att-src="website.image_url(message.author_id, 'image_small')" style="width: 50px; margin-right: 10px;"/>
|
||||
<div class="media-body">
|
||||
<h5 class="media-heading">
|
||||
<span t-field="message.author_id"/> <small>on <span t-field="message.date"/></small>
|
||||
|
@ -134,7 +134,7 @@
|
|||
<xpath expr="//h1" position="after">
|
||||
<section class="mb32 css_editable_mode_hidden hidden-print">
|
||||
<form id="comment" t-attf-action="/quote/#{quotation.id}/#{quotation.access_token}/post" method="POST">
|
||||
<img class="img pull-left img-rounded" t-attf-src="/website/image/res.partner/{{ user_id.partner_id.id }}/image_small" style="width: 50px; margin-right: 10px;"/>
|
||||
<img class="img pull-left img-rounded" t-att-src="website.image_url(user_id.partner_id, 'image_small')" style="width: 50px; margin-right: 10px;"/>
|
||||
<div class="pull-left mb32" style="width: 75%%">
|
||||
<textarea rows="4" name="comment" class="form-control" placeholder="Send us a note..."></textarea>
|
||||
<button type="submit" class="btn btn-primary mt8">Send</button>
|
||||
|
|
|
@ -178,9 +178,6 @@ class product_template(osv.Model):
|
|||
else:
|
||||
return self.set_sequence_bottom(cr, uid, ids, context=context)
|
||||
|
||||
def img(self, cr, uid, ids, field='image_small', context=None):
|
||||
return "/website/image/%s/%s/%s" % (self._name, ids[0], field)
|
||||
|
||||
class product_product(osv.Model):
|
||||
_inherit = "product.product"
|
||||
|
||||
|
@ -194,10 +191,6 @@ class product_product(osv.Model):
|
|||
'website_url': fields.function(_website_url, string="Website url", type="char"),
|
||||
}
|
||||
|
||||
def img(self, cr, uid, ids, field='image_small', context=None):
|
||||
temp_id = self.browse(cr, uid, ids[0], context=context).product_tmpl_id.id
|
||||
return "/website/image/product.template/%s/%s" % (temp_id, field)
|
||||
|
||||
class product_attribute(osv.Model):
|
||||
_inherit = "product.attribute"
|
||||
_columns = {
|
||||
|
|
|
@ -121,7 +121,7 @@ $('.oe_website_sale').each(function () {
|
|||
|
||||
if (product_id) {
|
||||
var $img = $(this).closest('tr.js_product, .oe_website_sale').find('span[data-oe-model^="product."][data-oe-type="image"] img');
|
||||
$img.attr("src", "/website/image/product.product/" + product_id + "/image");
|
||||
$img.attr("src", "/website/image/product.product-" + product_id + "-image");
|
||||
$img.parent().attr('data-oe-model', 'product.product').attr('data-oe-id', product_id)
|
||||
.data('oe-model', 'product.product').data('oe-id', product_id);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
</div>
|
||||
<div class="oe_product_image">
|
||||
<a itemprop="url" t-att-href="keep('/shop/product/%s' % slug(product), page=(pager['page']['num'] if pager['page']['num']>1 else None))">
|
||||
<img itemprop="image" class="img img-responsive" t-attf-src="/website/image/product.template/#{product.id}/image{{'' if product_image_big else '/300x300' }}"/>
|
||||
<img itemprop="image" class="img img-responsive" t-att-src="website.image_url(product, 'image', None if product_image_big else '300x300')"/>
|
||||
</a>
|
||||
</div>
|
||||
<section>
|
||||
|
@ -374,7 +374,7 @@
|
|||
<section t-attf-class="container oe_website_sale #{(compute_currency(product.lst_price) - product.price) > 0.1 and 'discount'}" id="product_detail">
|
||||
<div class="row">
|
||||
<div class="col-sm-7 col-md-7 col-lg-7">
|
||||
<span itemprop="image" t-field="product.image" t-field-options='{"widget": "image", "class": "product_detail_img"}'/>
|
||||
<span itemprop="image" class="agr" t-field="product.image" t-field-options='{"widget": "image", "class": "product_detail_img"}'/>
|
||||
</div><div class="col-sm-5 col-md-5 col-lg-4 col-lg-offset-1">
|
||||
<h1 itemprop="name" t-field="product.name">Product Name</h1>
|
||||
<span itemprop="url" style="display:none;" t-esc="'/shop/product/%s' % slug(product)"/>
|
||||
|
@ -603,7 +603,7 @@
|
|||
<ul class="media-list" id="comments-list" t-if="product.website_message_ids">
|
||||
<li t-foreach="product.website_message_ids" t-as="message" class="media">
|
||||
<div class="media-body oe_msg">
|
||||
<img class="media-object pull-left oe_msg_avatar" t-attf-src="/website/image/res.partner/{{ message.author_id.id }}/image_small" style="width: 50px; margin-right: 10px;"/>
|
||||
<img class="media-object pull-left oe_msg_avatar" t-att-src="website.image_url(message.author_id, 'image_small')" style="width: 50px; margin-right: 10px;"/>
|
||||
<div class="media-body oe_msg_content">
|
||||
<t t-call="website.publish_short">
|
||||
<t t-set="object" t-value="message"/>
|
||||
|
@ -633,7 +633,7 @@
|
|||
</ul>
|
||||
<div class="css_editable_mode_hidden">
|
||||
<form id="comment" t-attf-action="/shop/product/comment/#{product.id}" method="POST">
|
||||
<img class="img pull-left img-rounded" t-attf-src="/website/image/res.partner/{{ user_id.partner_id.id }}/image_small" style="width: 50px; margin-right: 10px;"/>
|
||||
<img class="img pull-left img-rounded" t-att-src="website.image_url(user_id.partner_id, 'image_small')" style="width: 50px; margin-right: 10px;"/>
|
||||
<div class="pull-left mb32" style="width: 75%%">
|
||||
<textarea rows="3" name="comment" class="form-control" placeholder="Write a comment..."></textarea>
|
||||
<a class="btn btn-primary mt8 a-submit">Post</a>
|
||||
|
|
Loading…
Reference in New Issue