[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:
parent
89eb355069
commit
8ffc4d0a5a
|
@ -314,6 +314,23 @@ class Website(openerp.addons.web.controllers.main.Home):
|
||||||
'/website/image/<model>/<id>/<field>'
|
'/website/image/<model>/<id>/<field>'
|
||||||
], auth="public", website=True)
|
], auth="public", website=True)
|
||||||
def website_image(self, model, id, field, max_width=maxint, max_height=maxint):
|
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]
|
Model = request.registry[model]
|
||||||
|
|
||||||
response = werkzeug.wrappers.Response()
|
response = werkzeug.wrappers.Response()
|
||||||
|
@ -322,15 +339,17 @@ class Website(openerp.addons.web.controllers.main.Home):
|
||||||
|
|
||||||
ids = Model.search(request.cr, request.uid,
|
ids = Model.search(request.cr, request.uid,
|
||||||
[('id', '=', id)], context=request.context) \
|
[('id', '=', id)], context=request.context) \
|
||||||
or Model.search(request.cr, openerp.SUPERUSER_ID,
|
or Model.search(request.cr, openerp.SUPERUSER_ID,
|
||||||
[('id', '=', id), ('website_published', '=', True)], context=request.context)
|
[('id', '=', id), ('website_published', '=', True)], context=request.context)
|
||||||
|
|
||||||
if not ids:
|
if not ids:
|
||||||
return self.placeholder(response)
|
return self.placeholder(response)
|
||||||
|
|
||||||
|
presized = '%s_big' % field
|
||||||
concurrency = '__last_update'
|
concurrency = '__last_update'
|
||||||
[record] = Model.read(request.cr, openerp.SUPERUSER_ID, [id],
|
[record] = Model.read(request.cr, openerp.SUPERUSER_ID, [id],
|
||||||
[concurrency, field], context=request.context)
|
[concurrency, field, presized],
|
||||||
|
context=request.context)
|
||||||
|
|
||||||
if concurrency in record:
|
if concurrency in record:
|
||||||
server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT
|
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:
|
if response.status_code == 304:
|
||||||
return response
|
return response
|
||||||
|
|
||||||
data = record[field].decode('base64')
|
data = (record.get(presized) or record[field]).decode('base64')
|
||||||
fit = int(max_width), int(max_height)
|
|
||||||
|
|
||||||
buf = cStringIO.StringIO(data)
|
image = Image.open(cStringIO.StringIO(data))
|
||||||
|
|
||||||
image = Image.open(buf)
|
|
||||||
image.load()
|
|
||||||
response.mimetype = Image.MIME[image.format]
|
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
|
w, h = image.size
|
||||||
max_w, max_h = fit
|
max_w, max_h = fit
|
||||||
|
|
||||||
if w < max_w and h < max_h:
|
if w < max_w and h < max_h:
|
||||||
response.data = data
|
response.set_data(data)
|
||||||
else:
|
else:
|
||||||
image.thumbnail(fit, Image.ANTIALIAS)
|
image.thumbnail(fit, Image.ANTIALIAS)
|
||||||
image.save(response.stream, image.format)
|
image.save(response.stream, image.format)
|
||||||
# invalidate content-length computed by make_conditional as writing
|
# invalidate content-length computed by make_conditional as
|
||||||
# to response.stream does not do it (as of werkzeug 0.9.3)
|
# writing to response.stream does not do it (as of werkzeug 0.9.3)
|
||||||
del response.headers['Content-Length']
|
del response.headers['Content-Length']
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -580,10 +580,26 @@ class ir_attachment(osv.osv):
|
||||||
return hashlib.new('sha1', attachment_dict['datas']).hexdigest()
|
return hashlib.new('sha1', attachment_dict['datas']).hexdigest()
|
||||||
return None
|
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 = {
|
_columns = {
|
||||||
'datas_checksum': fields.function(_datas_checksum, size=40,
|
'datas_checksum': fields.function(_datas_checksum, size=40,
|
||||||
string="Datas checksum", type='char', store=True, select=True),
|
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):
|
def create(self, cr, uid, values, context=None):
|
||||||
|
|
Loading…
Reference in New Issue