Quantcast
Channel: Recent posts across whole site
Viewing all articles
Browse latest Browse all 49221

Python code using XML-RPC to create a node and upload/attach a file.

$
0
0

I've searched the web looking for something more than a "create a node" example for Drupal Services. There are some good examples for Flash/Flex and some bits and pieces in Python or PHP but nothing that helps me to figure out what I am doing wrong.

Since my client is planning to develop a cross platform application that interacts with their Drupal site, I thought I would create a sample app in Python - just to show the Flash, iPhone, Droid, Blackberry developers how the Drupal Services API works.

I may be doing something dumb. I've been programming for over 20 years but I have never really done anything serious with Python. I have a really hard time mapping what I know in PHP onto Python.

But, since the code will be of use to others and I really want to figure this out, I am posting it here and asking for help with one area of the sample app. I can't figure out how to attach the file upload to the node. I think it's because I am not passing the data correctly. Has anyone made this work when calling the XML-RPC server?

#! /usr/bin/python

import os.path, sys, time, mimetypes, xmlrpclib, pprint, base64
pp = pprint.PrettyPrinter()

config = {
  'url': 'http://example.com/services/xmlrpc',
  'username': 'developer',
  'password': 'bZdKNTv7XB8C',
}

# Make initial connection to service, then login as developer
server = xmlrpclib.Server(config['url'], allow_none=True);
connection = server.system.connect();
session = server.user.login(connection['sessid'], config['username'], config['password']);
sessid = session['sessid'];
user = session['user'];

timestamp = str(int(time.time()))

## Load a movie file - get size, mimetype
filename = 'testfile.MOV'
filesize = os.stat(filename).st_size
filemime = mimetypes.guess_type(filename)
fd = open(filename, 'rb')
video_file = fd.read()
fd.close()

# Create file_obj with encoded file data
file_obj = {
   'file': base64.b64encode(video_file),
    'filename': filename,
    'filepath': 'sites/default/files/' + filename,
'filesize': filesize,
    'timestamp': timestamp,
  'uid': user['uid'],
    'filemime': filemime,
}

# Save the file to the server
try:
  f = server.file.save(sessid, file_obj)

except xmlrpclib.Fault, err:
   print "A fault occurred"
print "Fault code: %d" % err.faultCode
   print "Fault string: %s" % err.faultString

else:
    pp.pprint(f) # DEBUG


# Get the new file from the server (verify)  DEBUG
try:
ff = server.file.get(sessid, f)

except xmlrpclib.Fault, err:
  print "A fault occurred"
print "Fault code: %d" % err.faultCode
   print "Fault string: %s" % err.faultString

else:
    # We have the new file info - we need this in case the name of the file was changed when sotred on the server
  # pp.pprint(ff) # DEBUG
   
   del ff['file'] # We don't need this - free it
  
   node_files = {
     'fid': f,
        'filemime': filemime,
        'filename': ff['filename'],
        'filepath': ff['filepath'],
        'filesize': filesize,
        'status': '1',
     'timestamp': timestamp,
      'uid': user['uid'],
    }
 
   # Create the node object and refernce the new fid just created
node = {
     'type': 'video_local',
     'status': 1,
     'type': 'video_local',
     'title': 'Remote Test ' + timestamp,
   'body': 'This is a test created from a remote app',
    'uid': user['uid'],
    'name': user['name'],
      'changed': timestamp,
    'files': {},
     'field_video_overlay' : [
      {'value': 'Here is some CCK field text'},
    ],
   }
 
   # my latest attempt to figure out how to get node->files in the right format for the node.save method
   # please don't laugh - I am just grasping at straws here - ive tried all the lists and dictionary formats.
    node['files'][f] = node_files
   
   pp.pprint(node) # DEBUG
   
   try:
       n = server.node.save(sessid, node)
     nn = server.node.get(sessid,int(n),[])

   except xmlrpclib.Fault, err:
       print "A fault occurred"
     print "Fault code: %d" % err.faultCode
       print "Fault string: %s" % err.faultString
  
   else:
      pp.pprint(n) # DEBUG
       pp.pprint(nn) # DEBUG

The code formatter makes it appear that some of the code is not indented correctly. See the attached file for working code

This code runs without errors - connects, logs in, uploads a file, gets the fid, creates a node - but in the end, the new node does not include the file attachment.

Does anyone know what I am doing wrong?

AttachmentSize
drupal_services_test.py_.txt2.82 KB

Viewing all articles
Browse latest Browse all 49221