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.7.tar.gz (16.7 kB view details)

Uploaded Source

Built Distribution

pg_lo_storage-0.1.7-py3-none-any.whl (8.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pg_lo_storage-0.1.7.tar.gz
  • Upload date:
  • Size: 16.7 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.7.tar.gz
Algorithm Hash digest
SHA256 8b53a5f60f8018786a5f5ea7d6fbda3d852008c92b60fdb71324d1c00ae16a6c
MD5 f9137c713b274f1b96308b3b9e4accb7
BLAKE2b-256 20da8ba86fe563b9a3597ff145488d47bcd0ae3227d70a6577e8d44304ba857d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pg_lo_storage-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 2c70ec401ec46ce369570173f7073b073bcce93553705b1c87a9a1066fed7f4c
MD5 27dd332cc4409c7f39dda7a4b6be6469
BLAKE2b-256 9d091d20a98afcb0bb5bdb8e6c7b8c5e8c8e09c39ab31426e160db6bc99e42e3

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