Buckets

The bucket API implements the server-side of file-uploads and can be used to make files accessible over HTTP. It does not implement the browser-side, so it is best used with a library like lona-dropzone.

A bucket is basically a temporary directory, that gets created when a bucket is initialized with a request object, and closed automatically when the view, associated with the request, gets removed from the server.

Usage

from lona import View, Bucket, HTML, A


class BucketView(View):
    def handle_request(self, request):
        self.bucket = Bucket(
            request=request,
            on_add=self.on_add,        # optional
            on_delete=self.on_delete,  # optional
        )

        return HTML(
            A(
                'Bucket'
                href=self.bucket.get_url(),  # link to the bucket
                target='_blank',             # open link in new tab
                interactive=False,
            ),
        )

def on_add(self, file_names):
    # this method gets called whenever a file gets added (uploaded)
    # `file_names` is a list of strings

    pass


def on_delete(self, file_names):
    # this method gets called whenever a file gets deleted
    # `file_names` is a list of strings

    pass

Regardless of the URL of the view that opened the bucket, all buckets are accessible at /buckets/<request_id>/<bucket_id>.

To upload a file, issue a multipart POST request to /buckets/<request_id>/<bucket_id>/add.

To delete a file, issue a POST form request to /buckets/<request_id>/<bucket_id>/delete. The bucket will search for the form key name.

The URL prefix (/buckets/) can be changed using settings.BUCKETS_URL_PREFIX.

When Bucket.index is enabled, a generic frontend for listing, adding, and deleting files for a bucket is available at /buckets/<request_id>/<bucket_id>.

Arguments

lona.Bucket.__init__(
    self,
    request,
    max_files=None,
    max_size=None,
    index=True,
    on_add=None,
    on_delete=None,
)
    :request:    `lona.Request` object

    :max_files:  Maximum of files that can be added (uploaded) to the
                 bucket as integer. If max_files is `None` any amount of
                 files is allowed.

    :max_size:   Maximum of bytes that can be added (uploaded) to the
                 bucket as integer. If max_size is `None` any amount of
                 bytes is allowed.

    :index:      HTTP/HTML index is enabled.

    :on_add:     Optional callback which is called with the list of added
                 file names, when one or more files are added in a
                 POST request.

    :on_delete:  Optional callback which is called with the list of deleted
                 file names, when one or more files are deleted in a
                 POST request.

Methods

lona.Bucket.get_path(
    self,
    file_name='',
)
    Returns the absolute path to the given file name, as a string. If no
    file name is given, the absolute path to the buckets directory is
    returned.

    :file_name: optional string file name
lona.Bucket.get_file_names(
    self,
)
    Returns a list of all file names in the bucket as strings.
lona.Bucket.get_size(
    self,
)
    Returns the sum of the sizes of all files in bytes, contained in the
    bucket, as integer.
lona.Bucket.get_url(
    self,
    file_name='',
)
    Returns the URL to the given file name, as a string. If no file
    name is given, the URL to the buckets index is returned.

    :file_name: optional string file name
lona.Bucket.get_add_url(
    self,
)
    Returns the add (upload) URL of the bucket as a string.
lona.Bucket.get_delete_url(
    self,
)
    Returns the delete URL of the bucket as a string.

Customization

The Bucket index page can be customized by overriding the template lona/bucket.html.

<!-- templates/lona/bucket_index.html -->
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Lona Bucket {{ bucket.id }}</title>
    <style>
      body {
        font-family: sans-serif;
      }

      .delete-form {
        display: inline;
      }
    </style>
  </head>
  <body>
    <h1>Lona Bucket {{ bucket.id }}</h1>
    <table>
      <tr>
        <th>Max Files</th>
        <td>{{ repr(bucket.max_files) }}</td>
      </tr>
      <tr>
        <th>Max Size</th>
        <td>{{ repr(bucket.max_size) }}</td>
      </tr>
    </table>

    <h2>Add File</h2>
    <form class="add-form" action="{{ bucket.get_add_url() }}?redirect={{ bucket.get_url() }}" method="POST" enctype="multipart/form-data">
      <input type="file" name="files[]" multiple />
      <input type="submit" value="Add" />
    </form>

    <h2>Files</h2>
    {% set file_names=bucket.get_file_names() %}
    {% if file_names %}
      <ul>
        {% for file_name in file_names %}
          <li>
            <a href="{{ bucket.get_url(file_name=file_name) }}">{{ file_name }}</a>
            <form class="delete-form" action="{{ bucket.get_delete_url() }}?redirect={{ bucket.get_url() }}" method="POST">
              <input type="hidden" name="name" value="{{ file_name }}" />
              <input type="submit" value="Delete" />
            </form>
          </li>
        {% endfor %}
      </ul>
    {% else %}
      <p>No files yet</p>
    {% endif %}
  </body>
</html>