Software
1st December 2014 | By:

PyFileMaker – Integrating Python and Filemaker

PyFileMaker is a Python Library that makes it possible to work with FileMaker‘s XML API. You can use the Filemaker XML API to query a FileMaker database, create records, modify records, execute scripts and more.

During the creation of web applications there is often a need to use third party services or programs. One of them is FileMaker. FileMaker is a cross-platform relational database application. It contains a GUI layer that allows a user to easily create different relations between tables, create bespoke layouts, and easily run reports on the go. FileMaker is used as a database as it contains built-in server (which is SQL based, and to which you can actually execute direct SQL Queries if you want to!).

It also allows you to run a PHP server which is powerful but also quite inefficient and sluggish at times. To connect to FileMaker we can use the provided XML API instead, and that is what PyFileMaker is doing.

Functions already implemented

PyFileMaker has a lot of functions to work with already implemented. Some of these include:

  • Getting objects from db
  • Saving objects to db
  • Finding records
  • Sorting a query
  • Displaying meta data for particular layouts

When we’ve started working with the PyFileMaker library we noticed a few missing parts that are desperately needed:

  • No compatibility with FileMaker 13
  • Unable to execute scripts with/without parameters
  • Executing scripts in a chain with insert operations
  • Fetching files

In that situation one thing you can do is to extend the old library, write your own functions and integrate it together.

It turns out we can easily integrate PyFileMaker with FileMaker 13 and use then add in extra functionality that doesn’t exist in the original PyFileMaker Library.

All the standard functions work in the same way:

 from PyFileMaker import FMServer



fm = FMServer('login:password@filemaker.server.com')



fm.getDbNames()
 ['dbname','anoterdatabase']



fm.setDb('dbname')



fm.getLayoutNames()
 ['layoutname','anotherlayout']



fm.setLayout('layoutname')

New functionality

To execute the code below remember to specify a proper database and layout.

Execute scripts

The FileMaker API allows you to execute scripts. We can execute them in two ways: with or without parameters. We can send a parameter as a string separated by a special character that can be parsed from the FileMaker script that is being executed (this can be done by a simple replace statement in the Get(ScriptParameters) method on a FileMaker script and replacing the designated character eg: | with a carriage return character, which will then recognise each parameter as a value for GetValues()).




# execute script without parameters



 resp = fm.doScript('script_name')



# execute script with parameters
 parameters = "first|second|third"
 resp = fm.doScript('script_name', params=parameters)

Retrieve files

We can retrieve files from the Filemaker Server as a binary stream. To do this we need to point to the container field of the object and query its content.

Each object that contains a container field also contains a pre-generated  query (returned by FileMaker) to retrieve its content. We can easily find it by displaying all the fields for that given object:

 container_field = fm.doFind(id="10")
 container_field
 MODID = '10'
 RECORDID = '9791'
 creation_timestamp = '2014-06-25 16:25:05'
 id = '37'
 number = '199'
 email = 'some@email.co.uk'
 title = 'Rambo II'
 from_ts = '2014-06-25 00:00:00'
 ooh_zip = '/fmi/xml/cnt/data.zip?-db=DATABASE&-lay=layout&-field=ooh_zip&-recid=114'
 status = 'Complete'

In this case we need the `ooh_zip` field.

 file_name, file_extension, file_binary = fm_server.getFile(container.ooh_zip)

Execute script after another command

The doScriptAfter Method is taking the following arguments:

  1. Filemaker XML API Method
  2. Method arguments as kwargs(dict formatted)
  3. Filemaker Script name
  4. Filemaker Script arguments (optional)
 resp = fm.doScriptAfter(fm_server.doNew, {
 'first_name': 'Foo',
 'last_name': 'Bar',
 'ip': user_ip,
 'action': 'Download'
 },
 'script_name',
 'script_params'
 )

 Summary

Since sometimes you can’t avoid working with third party applications such as FileMaker, you need to use something that is able to satisfy your requirements. If there is nothing currently available then it is probably a good idea to extend the functionality and just share your work and ideas with the community.

Hope this helps somebody!

The lib can be found on:

Tags: , , ,

3 Comments

  1. Steve Dye
    7th April 2015 @ 17:26

    Hi,
    Thanks for posting pyfilemaker updates for FM13.

    Just testing out your module.
    Running with FM server 13.0.5.520 on iMac.
    Python 2.7
    Get DB connection OK and validates layout name and script name OK
    But getting error when running resp = fm.doScript(‘script_name’)
    File “C:python27libPyFileMakerFMServer.py”, line 262, on doScript
    return result.resultset[0] # Return Last Result
    IndexError: list index out of range

    Are there version dependencies for FM or Python that could cause this?

    Thanks for any guidance before I dig in….

    best regards,

    Steve

    • Marcin Kawa
      10th April 2015 @ 10:18

      Hello Steve,
      Thank you for catching this, it was actually a bug. I’ve fixed it already and pushed updated version to GitHub. The problem was that in my case the scripts were always returning some response so I’ve missed it. In your case, I believe there was no resultset returned from script hence the IndexError exception.

      Thanks,
      Marcin

  2. Bobby
    28th September 2016 @ 13:21

    Will PyFileMaker work with FM 11?