mirror of
https://github.com/camptocamp/odoo-cloud-platform.git
synced 2026-06-24 08:47:40 +00:00
Merge pull request #210 from p-tombez/mig14_attachments
[MIG] attachment modules: Migration to 14.0
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
{'name': 'Attachments on S3 storage',
|
{'name': 'Attachments on S3 storage',
|
||||||
'summary': 'Store assets and attachments on a S3 compatible object storage',
|
'summary': 'Store assets and attachments on a S3 compatible object storage',
|
||||||
'version': '13.0.1.0.0',
|
'version': "14.0.1.0.0",
|
||||||
'author': 'Camptocamp,Odoo Community Association (OCA)',
|
'author': 'Camptocamp,Odoo Community Association (OCA)',
|
||||||
'license': 'AGPL-3',
|
'license': 'AGPL-3',
|
||||||
'category': 'Knowledge Management',
|
'category': 'Knowledge Management',
|
||||||
@@ -14,5 +14,5 @@
|
|||||||
},
|
},
|
||||||
'website': 'https://www.camptocamp.com',
|
'website': 'https://www.camptocamp.com',
|
||||||
'data': [],
|
'data': [],
|
||||||
'installable': False,
|
'installable': True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
# Copyright 2016-2019 Camptocamp SA
|
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
|
|
||||||
from contextlib import closing
|
|
||||||
|
|
||||||
import odoo
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def migrate(cr, version):
|
|
||||||
if not version:
|
|
||||||
return
|
|
||||||
cr.execute("""
|
|
||||||
SELECT value FROM ir_config_parameter
|
|
||||||
WHERE key = 'ir_attachment.location'
|
|
||||||
""")
|
|
||||||
row = cr.fetchone()
|
|
||||||
bucket = os.environ.get('AWS_BUCKETNAME')
|
|
||||||
|
|
||||||
if row[0] == 's3' and bucket:
|
|
||||||
uid = odoo.SUPERUSER_ID
|
|
||||||
registry = odoo.modules.registry.Registry(cr.dbname)
|
|
||||||
new_cr = registry.cursor()
|
|
||||||
with closing(new_cr):
|
|
||||||
with odoo.api.Environment.manage():
|
|
||||||
env = odoo.api.Environment(new_cr, uid, {})
|
|
||||||
store_local = env['ir.attachment'].search(
|
|
||||||
[('store_fname', '=like', 's3://%'),
|
|
||||||
'|', ('res_model', '=', 'ir.ui.view'),
|
|
||||||
('res_field', 'in', ['image_small',
|
|
||||||
'image_medium',
|
|
||||||
'web_icon_data'])
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
_logger.info(
|
|
||||||
'Moving %d attachments from S3 to DB for fast access',
|
|
||||||
len(store_local)
|
|
||||||
)
|
|
||||||
for attachment_id in store_local.ids:
|
|
||||||
# force re-storing the document, will move
|
|
||||||
# it from the object storage to the database
|
|
||||||
|
|
||||||
# This is a trick to avoid having the 'datas' function
|
|
||||||
# fields computed for every attachment on each
|
|
||||||
# iteration of the loop. The former issue being that
|
|
||||||
# it reads the content of the file of ALL the
|
|
||||||
# attachments on each loop.
|
|
||||||
try:
|
|
||||||
env.clear()
|
|
||||||
attachment = env['ir.attachment'].browse(attachment_id)
|
|
||||||
_logger.info('Moving attachment %s (id: %s)',
|
|
||||||
attachment.name, attachment.id)
|
|
||||||
attachment.write({'datas': attachment.datas})
|
|
||||||
new_cr.commit()
|
|
||||||
except:
|
|
||||||
new_cr.rollback()
|
|
||||||
@@ -107,7 +107,7 @@ class IrAttachment(models.Model):
|
|||||||
return bucket
|
return bucket
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _store_file_read(self, fname, bin_size=False):
|
def _store_file_read(self, fname):
|
||||||
if fname.startswith('s3://'):
|
if fname.startswith('s3://'):
|
||||||
s3uri = S3Uri(fname)
|
s3uri = S3Uri(fname)
|
||||||
try:
|
try:
|
||||||
@@ -122,8 +122,6 @@ class IrAttachment(models.Model):
|
|||||||
bucket.meta.client.head_object(
|
bucket.meta.client.head_object(
|
||||||
Bucket=bucket.name, Key=key
|
Bucket=bucket.name, Key=key
|
||||||
)
|
)
|
||||||
if bin_size:
|
|
||||||
return bucket.Object(key).content_length
|
|
||||||
with io.BytesIO() as res:
|
with io.BytesIO() as res:
|
||||||
bucket.download_fileobj(key, res)
|
bucket.download_fileobj(key, res)
|
||||||
res.seek(0)
|
res.seek(0)
|
||||||
@@ -135,7 +133,7 @@ class IrAttachment(models.Model):
|
|||||||
)
|
)
|
||||||
return read
|
return read
|
||||||
else:
|
else:
|
||||||
return super()._store_file_read(fname, bin_size)
|
return super()._store_file_read(fname)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _store_file_write(self, key, bin_data):
|
def _store_file_write(self, key, bin_data):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
{'name': 'Attachments on Swift storage',
|
{'name': 'Attachments on Swift storage',
|
||||||
'summary': 'Store assets and attachments on a Swift compatible object store',
|
'summary': 'Store assets and attachments on a Swift compatible object store',
|
||||||
'version': '13.0.1.0.0',
|
'version': "14.0.1.0.0",
|
||||||
'author': 'Camptocamp,Odoo Community Association (OCA)',
|
'author': 'Camptocamp,Odoo Community Association (OCA)',
|
||||||
'license': 'AGPL-3',
|
'license': 'AGPL-3',
|
||||||
'category': 'Knowledge Management',
|
'category': 'Knowledge Management',
|
||||||
@@ -17,5 +17,5 @@
|
|||||||
},
|
},
|
||||||
'website': 'https://www.camptocamp.com',
|
'website': 'https://www.camptocamp.com',
|
||||||
'data': [],
|
'data': [],
|
||||||
'installable': False,
|
'installable': True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ class IrAttachment(models.Model):
|
|||||||
return conn
|
return conn
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _store_file_read(self, fname, bin_size=False):
|
def _store_file_read(self, fname):
|
||||||
if fname.startswith('swift://'):
|
if fname.startswith('swift://'):
|
||||||
swifturi = SwiftUri(fname)
|
swifturi = SwiftUri(fname)
|
||||||
try:
|
try:
|
||||||
@@ -141,7 +141,7 @@ class IrAttachment(models.Model):
|
|||||||
'Error reading object from Swift object store')
|
'Error reading object from Swift object store')
|
||||||
return read
|
return read
|
||||||
else:
|
else:
|
||||||
return super()._store_file_read(fname, bin_size)
|
return super()._store_file_read(fname)
|
||||||
|
|
||||||
def _store_file_write(self, key, bin_data):
|
def _store_file_write(self, key, bin_data):
|
||||||
if self._storage() == 'swift':
|
if self._storage() == 'swift':
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
{'name': 'Base Attachment Object Store',
|
{'name': 'Base Attachment Object Store',
|
||||||
'summary': 'Base module for the implementation of external object store.',
|
'summary': 'Base module for the implementation of external object store.',
|
||||||
'version': '13.0.1.1.0',
|
'version': "14.0.1.0.0",
|
||||||
'author': 'Camptocamp,Odoo Community Association (OCA)',
|
'author': 'Camptocamp,Odoo Community Association (OCA)',
|
||||||
'license': 'AGPL-3',
|
'license': 'AGPL-3',
|
||||||
'category': 'Knowledge Management',
|
'category': 'Knowledge Management',
|
||||||
'depends': ['base'],
|
'depends': ['base'],
|
||||||
'website': 'http://www.camptocamp.com',
|
'website': 'http://www.camptocamp.com',
|
||||||
'data': ['data/res_config_settings_data.xml'],
|
'data': ['data/res_config_settings_data.xml'],
|
||||||
'installable': False,
|
'installable': True,
|
||||||
'auto_install': True,
|
'auto_install': True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,13 +178,13 @@ class IrAttachment(models.Model):
|
|||||||
return super()._get_datas_related_values(data, mimetype)
|
return super()._get_datas_related_values(data, mimetype)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _file_read(self, fname, bin_size=False):
|
def _file_read(self, fname):
|
||||||
if self._is_file_from_a_store(fname):
|
if self._is_file_from_a_store(fname):
|
||||||
return self._store_file_read(fname, bin_size=bin_size)
|
return self._store_file_read(fname)
|
||||||
else:
|
else:
|
||||||
return super()._file_read(fname, bin_size=bin_size)
|
return super()._file_read(fname)
|
||||||
|
|
||||||
def _store_file_read(self, fname, bin_size=False):
|
def _store_file_read(self, fname):
|
||||||
storage = fname.partition('://')[0]
|
storage = fname.partition('://')[0]
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
'No implementation for %s' % (storage,)
|
'No implementation for %s' % (storage,)
|
||||||
@@ -202,16 +202,15 @@ class IrAttachment(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _file_write(self, value, checksum):
|
def _file_write(self, bin_data, checksum):
|
||||||
location = self.env.context.get('storage_location') or self._storage()
|
location = self.env.context.get('storage_location') or self._storage()
|
||||||
if location in self._get_stores():
|
if location in self._get_stores():
|
||||||
bin_data = base64.b64decode(value)
|
|
||||||
key = self.env.context.get('force_storage_key')
|
key = self.env.context.get('force_storage_key')
|
||||||
if not key:
|
if not key:
|
||||||
key = self._compute_checksum(bin_data)
|
key = self._compute_checksum(bin_data)
|
||||||
filename = self._store_file_write(key, bin_data)
|
filename = self._store_file_write(key, bin_data)
|
||||||
else:
|
else:
|
||||||
filename = super()._file_write(value, checksum)
|
filename = super()._file_write(bin_data, checksum)
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Base FileURL Field",
|
"name": "Base FileURL Field",
|
||||||
"summary": "Implementation of FileURL type fields",
|
"summary": "Implementation of FileURL type fields",
|
||||||
"version": "13.0.1.0.0",
|
"version": "14.0.1.0.0",
|
||||||
"category": "Technical Settings",
|
"category": "Technical Settings",
|
||||||
'author': 'Camptocamp, Odoo Community Association (OCA)',
|
'author': 'Camptocamp, Odoo Community Association (OCA)',
|
||||||
'license': 'AGPL-3',
|
'license': 'AGPL-3',
|
||||||
@@ -11,5 +11,5 @@
|
|||||||
"base_attachment_object_storage",
|
"base_attachment_object_storage",
|
||||||
],
|
],
|
||||||
"auto_install": False,
|
"auto_install": False,
|
||||||
"installable": False,
|
"installable": True,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user