Adding new download formats

While the Aristotle-MDR framework has a PDF download extension, it may be desired to download metadata stored within a registry in a variety of download formats. Rather than include these within the Aristotle-MDR core codebase, additional download formats can be developed included via the download API.

Creating a download module

A download module is a specialised class, that sub-classes aristotle_mdr.downloader.DownloaderBase and provides an appropriate download or bulk_download method.

A download module is just a Django app that includes a specific set of files for generating downloads. The only files required in your app are:

  • __init__.py - to declare the app as a python module
  • downloader.py - where your download classes will be stored

Other modules can be written, for example a download module may define models for recording a number of times an item is downloaded.

Writing a metadata_register

Your downloader class must contain a register of download types and the metadata concept types which this module provides downloads for. This takes one of the following forms which define which concepts can be downloaded as in the output format:

class CSVExample(DownloaderBase):
    download_type = "csv"
    metadata_register = {'aristotle_mdr': ['valuedomain']}

class XLSExample(DownloaderBase):
    download_type = "xls"
    metadata_register = {'aristotle_mdr': ['__all__']}

class PDFExample(DownloaderBase):
    download_type = "pdf"
    metadata_register = '__template__'

class TXTExample(DownloaderBase):
    download_type = "txt"
    metadata_register = '__all__'

Describing these options, these classes specifies the following downloads:

  • csv provides downloads for Value Domains in the Aristotle-MDR module
  • xls provides downloads for all metadata types in the Aristotle-MDR module
  • pdf provides downloads for items in all modules, only if they have a download template
  • txt provides downloads for all metadata types in all modules

Each download class must also define a class method with the following signature:

def download(cls, request, item):

This is called from Aristotle-MDR when it catches a download type that has been registered for this module. The arguments are:

  • request - the request object that was used to call the download view. The current user trying to download the item can be gotten by calling request.user.
  • item - the item to be downloaded, as retrieved from the database.

Note: If a download method is called the user has been verified to have permissions to view the requested item only. Permissions for other items will have to be checked within the download method.

For more information see the DownloaderBase class below:

class aristotle_mdr.downloader.DownloaderBase[source]

Required class properties:

  • description: a description of the downloader type
  • download_type: the extension or name of the download to support
  • icon_class: the font-awesome class
  • metadata_register: can be one of:
    • a dictionary with keys corresponding to django app labels and values as lists of models within that app the downloader supports
    • the string “__all__” indicating the downloader supports all metadata types
    • the string “__template__” indicating the downloader supports any metadata type with a matching download template
classmethod bulk_download(request, item)[source]

This method must be overriden and return a bulk downloaded set of items as an appropriate django response

classmethod download(request, item)[source]

This method must be overriden and return the downloadable object as an appropriate django response

How the download view works

aristotle_mdr.views.downloads.download(request, download_type, iid=None)[source]

By default, aristotle_mdr.views.download is called whenever a URL matches the pattern defined in aristotle_mdr.urls_aristotle:

download/(?P<download_type>[a-zA-Z0-9\-\.]+)/(?P<iid>\d+)/?

This is passed into download which resolves the item id (iid), and determines if a user has permission to view the requested item with that id. If a user is allowed to download this file, download iterates through each download type defined in ARISTOTLE_SETTINGS.DOWNLOADERS.

A download option tuple takes the following form form:

('file_type','display_name','font_awesome_icon_name','module_name'),

With file_type allowing only ASCII alphanumeric and underscores, display_name can be any valid python string, font_awesome_icon_name can be any Font Awesome icon and module_name is the name of the python module that provides a downloader for this file type.

For example, the Aristotle-PDF with Aristotle-MDR is a PDF downloader which has the download definition tuple:

('pdf','PDF','fa-file-pdf-o','aristotle_pdr'),

Where a file_type multiple is defined multiple times, the last matching instance in the tuple is used.

Next, the module that is defined for a file_type is dynamically imported using exec, and is wrapped in a try: except block to catch any exceptions. If the module_name does not match the regex ^[a-zA-Z0-9\_]+$ download raises an exception.

If the module is able to be imported, downloader.py from the given module is imported, this file MUST have a download function defined which returns a Django HttpResponse object of some form.