Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 40 additions & 45 deletions attachments_to_filesystem/models/ir_attachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,92 +22,87 @@
import logging
from datetime import datetime
from dateutil.relativedelta import relativedelta
from openerp.osv.orm import Model
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp import api, fields, models


class IrAttachment(Model):
class IrAttachment(models.Model):
_inherit = 'ir.attachment'

def _attachments_to_filesystem_init(self, cr, uid, context=None):
@api.model
def _attachments_to_filesystem_init(self):
"""Set up config parameter and cron job"""
module_name = __name__.split('.')[-3]
ir_model_data = self.pool['ir.model.data']
ir_cron = self.pool['ir.cron']
location = self.pool['ir.config_parameter'].get_param(
cr, uid, 'ir_attachment.location')
ir_model_data = self.env['ir.model.data']
location = self.env['ir.config_parameter'].get_param(
'ir_attachment.location'
)
if location:
# we assume the user knows what she's doing. Might be file:, but
# also whatever other scheme shouldn't matter. We want to bring
# data from the database to there
pass
else:
ir_model_data._update(
cr, uid, 'ir.config_parameter', module_name,
'ir.config_parameter', module_name,
{
'key': 'ir_attachment.location',
'value': 'file',
},
xml_id='config_parameter_ir_attachment_location',
context=context)
xml_id='config_parameter_ir_attachment_location'
)

# synchronous behavior
if self.pool['ir.config_parameter'].get_param(
cr, uid, 'attachments_to_filesystem.move_during_init'):
self._attachments_to_filesystem_cron(cr, uid, context, limit=None)
if self.env['ir.config_parameter'].get_param(
'attachments_to_filesystem.move_during_init'
):
self._attachments_to_filesystem_cron(limit=None)
return

# otherwise, configure our cronjob to run next night
user = self.pool['res.users'].browse(cr, uid, uid, context=context)
user = self.env.user
next_night = datetime.now() + relativedelta(
hour=01, minute=42, second=0)
user_tz = user.tz or 'UTC'
next_night = pytz.timezone(user_tz).localize(next_night).astimezone(
pytz.utc).replace(tzinfo=None)
if next_night < datetime.now():
next_night += relativedelta(days=1)
ir_cron.write(
cr, uid,
[
ir_model_data.get_object_reference(
cr, uid, module_name, 'cron_move_attachments')[1],
],
{
'nextcall':
next_night.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
'doall': True,
'interval_type': 'days',
'interval_number': 1,
},
context=context)
self.env.ref('%s.cron_move_attachments' % module_name).write({
'nextcall': fields.Datetime.to_string(next_night),
'doall': True,
'interval_type': 'days',
'interval_number': 1,
})

def _attachments_to_filesystem_cron(self, cr, uid, context=None,
limit=10000):
@api.model
def _attachments_to_filesystem_cron(self, limit=10000):
"""Do the actual moving"""
limit = int(
self.pool['ir.config_parameter'].get_param(
cr, uid, 'attachments_to_filesystem.limit', '0')) or limit
ir_attachment = self.pool['ir.attachment']
self.env['ir.config_parameter'].get_param(
'attachments_to_filesystem.limit', '0')) or limit
ir_attachment = self.env['ir.attachment']
attachment_ids = ir_attachment.search(
cr, uid, [('db_datas', '!=', False)], limit=limit, context=context)
[('db_datas', '!=', False)], limit=limit)
logging.info('moving %d attachments to filestore', len(attachment_ids))
# attachments can be big, so we read every attachment on its own
for counter, attachment_id in enumerate(attachment_ids, start=1):
attachment_data = ir_attachment.read(
cr, uid, [attachment_id], ['datas', 'res_model'],
context=context)[0]
if attachment_data['res_model'] and not self.pool.get(
[attachment_id], ['datas', 'res_model']
)[0]
if attachment_data['res_model'] and not self.env.registry.get(
attachment_data['res_model']):
logging.warning(
'not moving attachment %d because it links to unknown '
'model %s', attachment_id, attachment_data['res_model'])
continue
ir_attachment.write(
cr, uid, [attachment_id],
{
'datas': attachment_data['datas'],
'db_datas': False,
},
context=context)
try:
ir_attachment.write(
[attachment_id],
{
'datas': attachment_data['datas'],
'db_datas': False,
})
except Exception:
logging.exception('Error moving attachment #%d', attachment_id)
if not counter % (len(attachment_ids) / 100 or limit):
logging.info('moving attachments: %d done', counter)