Pyramid integration

This page describes how to integrate keepluggable into your existing Pyramid application by reusing the code in the keepluggable.web.pyramid package.

Of course you can always write your own Pyramid integration reusing our code.

Configuration

keepluggable is a pluggable sub-application that can be integrated into your app multiple times. Each time you start by creating a section in your INI file. Section names must start with “keepluggable “. In the following example 2 keepluggable storages are configured:

[app:main]
# Pyramid application settings go in this section.
# (...)

[keepluggable avatars]
# User images storage settings here
# (...)

[keepluggable products]
# The storage for product images is configured in this section.
# (...)

At application startup

For each keepluggable storage, you need to instantiate an Orchestrator:

from keepluggable.orchestrator import Orchestrator

Orchestrator.from_ini(
    'avatars',                    # A unique name for this storage
    global_settings['__file__'],  # Path to INI configuration file
)

This will cause keepluggable to read the “[keepluggable avatars]” section you created earlier and set it up.

Repeat the call for each separate storage:

Orchestrator.from_ini(
    'products',                   # A unique name for this storage
    global_settings['__file__'],  # Path to your INI configuration file
)

The Orchestrator class keeps track of its instances so that later, in a request, you can retrieve an instance like this:

orchestrator = Orchestrator.instances['avatars']

Create a resource for the file storage

We use traversal and provide a context resource mixin class which you must inherit in your own resource class:

from keepluggable.web.pyramid.resources import BaseFilesResource


class FilesResource(YourBaseResourceClass, BaseFilesResource):
    keepluggable_name = "avatars"  # name of the storage for this resource
    namespace = 'myapp42'

The keepluggable_name variable above lets the resource determine which of the keepluggable storages is “mounted” on this URL.

You can use the namespace setting to further separate files. So this resource knows which namespace it manages. It was done above through a static class variable, but it need not be so static. It could be a Python property, or an instance variable set by the constructor. Your code might calculate the namespace based on the URL.

More information is available on the component documentation: keepluggable.web.pyramid.resources

We provide a RESTful HTTP API done with Pyramid

Once you have a resource, you can attach views to it. See keepluggable.web.pyramid.views.

Below we provide a description of what the HTTP API does.

List existing files and images

GET example URL: /users/joe/files

The JSON-encoded response contains, in its “items” variable, an array of metadata objects about the original uploaded files. Each metadata contains data such as id, md5, length, image_height, image_width, image_format, file_name, version etc.

For each metadata, if versions of the original were created (e. g. smaller images), they are inside the “versions” variable. They contain an “href” variable indicating the payload location.

Upload one or more files or images

POST example URL: /users/joe/files

Other requests in this API must be in JSON format. Not this method! It must be a common multipart/form-data POST request.

It must contain the upload(s) in a files variable. You may also specify other variables – they are forwarded to your metadata storage backend.

Most of the metadata is discovered on the server. This includes file length, file name, MD5 hash, image format, image size etc.

The response is in JSON format (only the request isn’t) and it has items, an array in which each element is either the metadata for an accepted file, or details of upload failure. You can test failures by uploading zero-length files. The order in the items array is the same as the uploaded files.

Each failure has these variables:

  • "upload_failed": true: A flag for you to identify the failures

  • error_type: An error title, such as ‘“MY_FILE” was not stored. ‘

  • error_msg: A message that should be displayed to the user

  • file_name: The uploaded file name

  • mime_type: The MIME type reported by the browser

Updating the metadata of a file or image

PUT example URL: /users/joe/files/<id>/@@metadata

In this case, the file is NOT identified by its MD5, but by its ID. There are 2 modes of operation:

  • If you do not implement and indicate a Colander schema, every variable in the request is set on the metadata entity.

  • If you do implement and indicate a Colander schema, it gets used for validation and the metadata entity only receives the “cleaned” data.

The most important variable that is set through this method is the description, since it is usually not sent with the original upload request.

Delete/remove a file

DELETE example URL: /users/joe/files/<MD5>

That last bit in the URL must be the MD5 hash (also known as the “key”) of the file that should be deleted.

This method deletes all the derivative files as well (“versions”). It deletes payloads as well as metadata entities.

No request body is necessary. May return 404 Not Found if the resource does not exist. When happy, returns 204 No Content, meaning the resource was deleted and the response has no body.