Muchas veces necesitamos importar imágenes en forma masiva. Ayer por ejemplo un cliente me pidio que le importe un directorio con imágenes de productos en Odoo. Lo hice con xmlrpc, mediante este script que pienso explicar en este post (así no se me olvidan los detalles para futuras importaciones).
El escenario es este. Tenemos un directorio con imágenes y cada imagen es un archivo de formato PNG y el nombre del archivo es el SKU (campo default_code) del producto.
Más alla que vamos a utilizar xmlrpc (mi método favorito para la actualización masiva de datos en Odoo) vamos a utilizar también la librería os de Python para obtener la lista de archivos.
onlyfiles = [f for f in listdir(getcwd()) if isfile(join(getcwd(), f))]
Lo que nos devuelve una lista de los archivos en el directorio actual (para eso utilizamos la función getcwd para obtener el directorio corriente y listdir para listar los archivos de un directorio). Paso seguido iteramos la lista y por cada uno de los miembros, buscamos que el producto exista (chequeando que el nombre sea el campo default_code del producto)
for i,onlyfile in enumerate(onlyfiles):
if onlyfile.endswith('.png'):
print(i,onlyfile)
default_code = onlyfile.replace('.png','')
domain = [[['default_code','=',default_code]]]
product_id = models.execute_kw(dbname,uid,pwd,'product.template','search',domain)
Luego abrimos el archivo y su contenido lo codificamos a base64 y lo preparamos para que pueda actualizar Odoo mediante xmlrpc
f = open(onlyfile,'rb')
image_encoded = base64.b64encode(f.read())
image_string = image_encoded.decode('utf-8')
Para finalmente crear la imagen en Odoo si la misma no existe:
image_domain = [[['product_tmpl_id','=',product_id[0]],['meli_force_pub','=',True]]]
product_image = models.execute_kw(dbname,uid,pwd,'product.image','search',image_domain)
if not product_image:
vals = {
'name': onlyfile,
'product_tmpl_id': product_id[0],
'image_1920': image_string,
'meli_force_pub': True,
}
return_id = models.execute_kw(dbname,uid,pwd,'product.image','create',[vals])
print(return_id)
El codigo completo se lo ve a continuacion
#!/usr/bin/python3
# import xmlrpc and openpyxl modules
from xmlrpc import client
from datetime import datetime
from os import listdir,getcwd
from os.path import isfile, join
import base64
url = 'http://www.myodoo.com.yy/'
common = client.ServerProxy('{}/xmlrpc/2/common'.format(url))
res = common.version()
user = 'ADMINUSER' #the user
pwd = 'ADMIN' #the user
dbname = 'MYDB'
uid = common.authenticate(dbname, user, pwd, {})
# prints Odoo version and UID to make sure we are connected
print(res)
print(uid)
models = client.ServerProxy('{}/xmlrpc/2/object'.format(url))
onlyfiles = [f for f in listdir(getcwd()) if isfile(join(getcwd(), f))]
missing = []
for i,onlyfile in enumerate(onlyfiles):
if onlyfile.endswith('.png'):
print(i,onlyfile)
default_code = onlyfile.replace('.png','')
domain = [[['default_code','=',default_code]]]
product_id = models.execute_kw(dbname,uid,pwd,'product.template','search',domain)
if not product_id:
missing.append(onlyfile)
else:
print(product_id)
f = open(onlyfile,'rb')
image_encoded = base64.b64encode(f.read())
image_string = image_encoded.decode('utf-8')
# print(content)
f.close()
image_domain = [[['product_tmpl_id','=',product_id[0]],['meli_force_pub','=',True]]]
product_image = models.execute_kw(dbname,uid,pwd,'product.image','search',image_domain)
if not product_image:
vals = {
'name': onlyfile,
'product_tmpl_id': product_id[0],
'image_1920': image_string,
'meli_force_pub': True,
}
return_id = models.execute_kw(dbname,uid,pwd,'product.image','create',[vals])
print(return_id)