Update Object Data with a CSV file import
Don't force users to manually update hundred's of products by editing them using the Plone interface. Offer a CSV (or Tab Delimited) import tool to quickly update all objects of a certain type.
For our purposes, we will use a TAB Delimited file to perform the import. The data from the import will come from a File object, which is uploaded by a user.
First, we retrieve the Tab Delimited file data. Perhaps not the optimal method, but we locate the file by using a portal_catalog search, then retrieve the file object.
from Products.CMFCore.utils import getToolByName
plone_utils = getToolByName(context, 'plone_utils')
try:
files = context.portal_catalog.searchResults(portal_type = 'File', path='/myplonesite/filepath')
file = files[0].getObject()
data = file.get_data()
except:
plone_utils.addPortalMessage('Could not read import file, please contact the administrator.')
return state.set(status='failure')Now, lets split the data into a list where each item in the list corresponds to one line of data.
data = data.split('\r\n')Defining a field map will make it easier to add more fields to your import down the line. This dictionary will help our script determine which fields are in which columns of the data file. Below, we have title in the first column and inventory in the second column.
fieldMap = { 'title' : 0, 'inventory' : 1 }We then parse through each line, capturing error messages and noting which data line they occurred on.
line = 0
errorLines = ''
for row in data:
line += 1
try:
fields = row.split('\t') # tab delimited
#make sure row has the correct number of fields
if len(fields) == len(fieldMap):
products = context.portal_catalog.searchResults(portal_type = 'StoreItem', title = fields[fieldMap['title']])
product = products[0].getObject()
# remove any commas from inventory numbers
fields[fieldMap['inventory']] = fields[fieldMap['inventory']].replace(',','')
# remove double quotation marks from inventory numbers (if any)
fields[fieldMap['inventory']] = fields[fieldMap['inventory']].replace('"','')
# ---> add additional fields here, following the setPrice model
product.setInventory(fields[fieldMap['inventory']])
else:
# add this line to the error message
if row != [] and row != '':
errorLines += str(line) + ', '
out = out + fields
except:
plone_utils.addPortalMessage('Error in import file, row #' + str(line))
return state.set(status='failure')Now, we conditionally return an error or success message based on the results of the import.
if errorLines != '':
msg = 'Not all items imported. Please verify the number of fields in lines ' + errorLines[0:-2]
else:
msg = 'Product data imported successfully.'
plone_utils.addPortalMessage(msg)
return state.set(status='success')
Need assistance with your project? Universal Web Services can help.
Contact us to request a quote.