[ADD] support for presized fields in website/image

also add presized field to attachments (automatically computed from datas)

bzr revid: xmo@openerp.com-20140317104251-ddsa9cfpq1vkk2k1
This commit is contained in:
Xavier Morel 2014-03-17 11:42:51 +01:00
parent 89eb355069
commit 8ffc4d0a5a
2 changed files with 51 additions and 13 deletions

View File

@ -314,6 +314,23 @@ class Website(openerp.addons.web.controllers.main.Home):
'/website/image/<model>/<id>/<field>'
], auth="public", website=True)
def website_image(self, model, id, field, max_width=maxint, max_height=maxint):
""" Fetches the requested field and ensures it does not go above
(max_width, max_height), resizing it if necessary.
Resizing is bypassed if the object provides a $field_big, which will
be interpreted as a pre-resized version of the base field.
If the record is not found or does not have the requested field,
returns a placeholder image via :meth:`~.placeholder`.
Sets and checks conditional response parameters:
* :mailheader:`ETag` is always set (and checked)
* :mailheader:`Last-Modified is set iif the record has a concurrency
field (``__last_update``)
The requested field is assumed to be base64-encoded image data in
all cases.
"""
Model = request.registry[model]
response = werkzeug.wrappers.Response()
@ -322,15 +339,17 @@ class Website(openerp.addons.web.controllers.main.Home):
ids = Model.search(request.cr, request.uid,
[('id', '=', id)], context=request.context) \
or Model.search(request.cr, openerp.SUPERUSER_ID,
[('id', '=', id), ('website_published', '=', True)], context=request.context)
or Model.search(request.cr, openerp.SUPERUSER_ID,
[('id', '=', id), ('website_published', '=', True)], context=request.context)
if not ids:
return self.placeholder(response)
presized = '%s_big' % field
concurrency = '__last_update'
[record] = Model.read(request.cr, openerp.SUPERUSER_ID, [id],
[concurrency, field], context=request.context)
[concurrency, field, presized],
context=request.context)
if concurrency in record:
server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
@ -354,25 +373,28 @@ class Website(openerp.addons.web.controllers.main.Home):
if response.status_code == 304:
return response
data = record[field].decode('base64')
fit = int(max_width), int(max_height)
data = (record.get(presized) or record[field]).decode('base64')
buf = cStringIO.StringIO(data)
image = Image.open(buf)
image.load()
image = Image.open(cStringIO.StringIO(data))
response.mimetype = Image.MIME[image.format]
# record provides a pre-resized version of the base field, use that
# directly
if record.get(presized):
response.set_data(data)
return response
fit = int(max_width), int(max_height)
w, h = image.size
max_w, max_h = fit
if w < max_w and h < max_h:
response.data = data
response.set_data(data)
else:
image.thumbnail(fit, Image.ANTIALIAS)
image.save(response.stream, image.format)
# invalidate content-length computed by make_conditional as writing
# to response.stream does not do it (as of werkzeug 0.9.3)
# invalidate content-length computed by make_conditional as
# writing to response.stream does not do it (as of werkzeug 0.9.3)
del response.headers['Content-Length']
return response

View File

@ -580,10 +580,26 @@ class ir_attachment(osv.osv):
return hashlib.new('sha1', attachment_dict['datas']).hexdigest()
return None
def _datas_big(self, cr, uid, ids, name, arg, context=None):
result = dict.fromkeys(ids, False)
if context and context.get('bin_size'):
return result
for record in self.browse(cr, uid, ids, context=context):
if not record.datas: continue
try:
result[record.id] = openerp.tools.image_resize_image_big(record.datas)
except IOError: # apparently the error PIL.Image.open raises
pass
return result
_columns = {
'datas_checksum': fields.function(_datas_checksum, size=40,
string="Datas checksum", type='char', store=True, select=True),
'website_url': fields.function(_website_url_get, string="Attachment URL", type='char')
'website_url': fields.function(_website_url_get, string="Attachment URL", type='char'),
'datas_big': fields.function (_datas_big, type='binary', store=True,
string="Resized file content"),
}
def create(self, cr, uid, values, context=None):