Skip to main content

Use PostgreSQL large objects for file storage

Project description

Use PostgreSQL large objects for file storage

This storage is created to store important files that belong to a user. It should not be used to store publicly available files or videos. The main benefit is that it works with transaction and you can create or delete a file and be confident that the file will still exist if the transaction is rolled back.

When the storage saves a file, a new filename with the template .<original_extension> is always created and the attribute upload_to is not used.

You can use DbFileIO without a storage.

The settings:

  • PG_LO_STORAGE_DB_FOR_READ - a database for read files (default is default)
  • PG_LO_STORAGE_DB_FOR_WRITE - a database for create and write files (default is default)

Example

Add model:

from django.db import models
from django.db.models.signals import post_delete, post_init, post_save
from django.dispatch import receiver
from pg_lo_storage.fields import DbFileField
from pg_lo_storage.storage import db_file_storage, DbFileStorage

class Invoice(models.Model):
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    # data = DbFileField(storage=DbFileStorage("/invoice"), null=True, blank=True)
    data = models.FileField(storage=DbFileStorage("/invoice"), null=True, blank=True)

@receiver(post_init, sender=Invoice)
def user_file_initialized(sender, instance: Invoice, **kwargs):
    instance._lo_prev_state = {
        'data': instance.data.name if instance.data else None,
    }

@receiver(post_save, sender=Invoice)
def user_file_saved(sender, instance: Invoice, created: bool, **kwargs):
    # this is safe because large objects support transactions
    if not created and hasattr(instance, '_lo_prev_state'):
        state = instance._lo_prev_state
        if state.get('data'):
            instance.data.storage.delete(state['data'])

@receiver(post_delete, sender=Invoice)
def user_file_deleted(sender, instance: Invoice, **kwargs):
    # this is safe because large objects support transactions
    if instance.data:
        instance.data.storage.delete(instance.data.name)

Add function to serve files:

from django.http import HttpResponseForbidden
from pg_lo_storage.views import db_serve

@login_required
def invlice_serve(request: HttpRequest, filename: str) -> HttpResponse:
    if not Invoice.objects.filter(user=request.user, data=filename).exists():
        return HttpResponseForbidden()
    return db_serve(request, filename)

Work as a file:

from django.db import transaction
from pg_lo_storage.storage import DbFileIO

@transaction.atomic
def write(loid: int, data: bytes, pos: int) -> int:
    # DbFileIO work only with transactions
    with DbFileIO(loid, "wb") as file:
        file.seek(pos)
        file.write(data)
        return file.loid

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pg_lo_storage-0.1.5.tar.gz (16.3 kB view details)

Uploaded Source

Built Distribution

pg_lo_storage-0.1.5-py3-none-any.whl (8.3 kB view details)

Uploaded Python 3

File details

Details for the file pg_lo_storage-0.1.5.tar.gz.

File metadata

  • Download URL: pg_lo_storage-0.1.5.tar.gz
  • Upload date:
  • Size: 16.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.4

File hashes

Hashes for pg_lo_storage-0.1.5.tar.gz
Algorithm Hash digest
SHA256 ba1f661f8d55f8c67dafe2618646032e141c5e3388f14cb71f1b74705cbd0723
MD5 15726d975ef22ff2e8ab0eac8696e334
BLAKE2b-256 5d735510550174591aecc0fd3ced28e62e4c01f39b7f0603b105cfbdcc1c7bdc

See more details on using hashes here.

File details

Details for the file pg_lo_storage-0.1.5-py3-none-any.whl.

File metadata

File hashes

Hashes for pg_lo_storage-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 0d3c97a2bf3c804c413abcaa7ef5b4f26d99e5ba499aaf6eab316eb00a290ae8
MD5 7f01ff52b7430c906eef48a7b5b27a70
BLAKE2b-256 e1a5a487e5657f90e74e0e45a30dc3342f39be90c0d8579cfe120e8dbf4126a9

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page