Skip to main content

Django storage backend for Supabase buckets

Project description

django-supabase-storage

A Django storage backend for Supabase buckets. Store your media and static files directly in Supabase Storage with a simple, drop-in replacement for Django's default storage backend.

Features

  • Direct Supabase Storage Integration: Upload files directly to Supabase buckets
  • No Local Storage: All files are stored in Supabase, not locally
  • Media & Static Storage: Separate storage backends for media and static files
  • Django Compatible: Works as a drop-in replacement for Django's default storage
  • Easy Configuration: Simple settings-based configuration
  • Production Ready: Comprehensive error handling and logging

Quick Start

1. Installation

pip install django-supabase-storage

2. Configuration

Add to your Django settings:

import os

# Supabase Configuration
SUPABASE_URL = os.getenv('SUPABASE_URL', 'https://your-project-id.supabase.co')
SUPABASE_KEY = os.getenv('SUPABASE_KEY', 'your-anon-public-key')
SUPABASE_BUCKET = os.getenv("SUPABASE_BUCKET_NAME", 'your-supabase-bucket-name')

# Storage Configuration (Django 4.2+)
STORAGES = {
    'default': {
        'BACKEND': 'django_supabase_storage.SupabaseMediaStorage',
    },
    'staticfiles': {
        'BACKEND': 'django_supabase_storage.SupabaseStaticStorage',
    },
}

# For Django < 4.2, use:
# DEFAULT_FILE_STORAGE = 'django_supabase_storage.SupabaseMediaStorage'
# STATICFILES_STORAGE = 'django_supabase_storage.SupabaseStaticStorage'

3. Set Environment Variables

Create a .env file:

SUPABASE_URL=https://your-project-id.supabase.co
SUPABASE_KEY=your-anon-public-key
SUPABASE_BUCKET_NAME=your-supabase-bucket-name

Using Storage Classes

Media Files Storage

For user uploads (images, documents, etc.):

from django.core.files.storage import default_storage

# Save a file to the media bucket
file_path = default_storage.save('uploads/myfile.pdf', file_content)

# Get the public URL
file_url = default_storage.url(file_path)

# Delete a file
default_storage.delete('uploads/myfile.pdf')

# Check if file exists
if default_storage.exists('uploads/myfile.pdf'):
    content = default_storage.open('uploads/myfile.pdf').read()

In Django Models:

from django.db import models

class UserProfile(models.Model):
    avatar = models.ImageField(upload_to='avatars/')
    resume = models.FileField(upload_to='resumes/')
    bio = models.TextField()

In Views:

from django.shortcuts import render
from django.core.files.storage import default_storage

def upload_avatar(request):
    if request.method == 'POST':
        file = request.FILES['avatar']
        # Save automatically goes to Supabase
        file_path = default_storage.save(f'avatars/{request.user.id}/{file.name}', file)
        file_url = default_storage.url(file_path)
        return render(request, 'success.html', {'url': file_url})
    return render(request, 'upload.html')

Static Files Storage

For CSS, JavaScript, and static images:

from django.templatetags.static import static

# In your Django templates
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<script src="{% static 'js/main.js' %}"></script>

Collecting Static Files:

# Django automatically collects static files to Supabase
python manage.py collectstatic

This uploads all your static files to the 'static' bucket in Supabase.

Storage Backends

SupabaseStorage (Base Class)

The base storage class for custom implementations:

from django_supabase_storage import SupabaseStorage

class CustomStorage(SupabaseStorage):
    folder_path = 'custom/'  # All files saved under this folder

SupabaseMediaStorage

Handles user-uploaded media files:

  • Bucket: 'media' (by default)
  • Folder: 'media'
  • Use Case: Profile pictures, documents, user uploads
from django_supabase_storage import SupabaseMediaStorage

# Direct usage
storage = SupabaseMediaStorage()
path = storage.save('documents/myfile.pdf', content)
url = storage.url(path)

SupabaseStaticStorage

Handles static application files:

  • Bucket: 'static' (by default)
  • Folder: 'static'
  • Use Case: CSS, JavaScript, application images
from django_supabase_storage import SupabaseStaticStorage

# Used automatically with collectstatic
# Or directly:
storage = SupabaseStaticStorage()
path = storage.save('js/app.js', content)
url = storage.url(path)

Complete Setup Example

Step 1: Create Supabase Buckets

  1. Go to supabase.com and create a project
  2. Navigate to StorageBuckets
  3. Create bucket named media
  4. Create bucket named static
  5. For each bucket, go to PoliciesNew PolicyAllow public read access

Step 2: Get Credentials

  1. Go to SettingsAPI
  2. Copy Project URL (SUPABASE_URL)
  3. Copy anon public key (SUPABASE_KEY)

Step 3: Configure Django

# settings.py
import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

# Supabase Configuration
SUPABASE_URL = os.getenv('SUPABASE_URL')
SUPABASE_KEY = os.getenv('SUPABASE_KEY')
SUPABASE_MEDIA_BUCKET = os.getenv('SUPABASE_MEDIA_BUCKET', 'media')
SUPABASE_STATIC_BUCKET = os.getenv('SUPABASE_STATIC_BUCKET', 'static')

# Storage Configuration
STORAGES = {
    'default': {
        'BACKEND': 'django_supabase_storage.SupabaseMediaStorage',
    },
    'staticfiles': {
        'BACKEND': 'django_supabase_storage.SupabaseStaticStorage',
    },
}

# Static files URL for Supabase
STATIC_URL = f'{SUPABASE_URL}/storage/v1/object/public/{SUPABASE_STATIC_BUCKET}/'

# Media files URL for Supabase
MEDIA_URL = f'{SUPABASE_URL}/storage/v1/object/public/{SUPABASE_MEDIA_BUCKET}/'

Step 4: Use in Your Application

# models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    cover_image = models.ImageField(upload_to='articles/')
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    avatar = models.ImageField(upload_to='avatars/')
    bio = models.TextField()

API Reference

SupabaseStorage Methods

# Save a file
path = storage.save('folder/filename.ext', content)

# Open/download a file
file_obj = storage.open('folder/filename.ext', mode='rb')
content = file_obj.read()

# Delete a file
storage.delete('folder/filename.ext')

# Check if file exists
exists = storage.exists('folder/filename.ext')

# List directory
dirs, files = storage.listdir('folder/')

# Get file size in bytes
size = storage.size('folder/filename.ext')

# Get public URL
url = storage.url('folder/filename.ext')

# Get file timestamps
created = storage.get_created_time('folder/filename.ext')
modified = storage.get_modified_time('folder/filename.ext')
accessed = storage.get_accessed_time('folder/filename.ext')

Troubleshooting

SUPABASE_URL or SUPABASE_KEY Not Configured

Error: ValueError: SUPABASE_URL is not configured!

Solution: Set environment variables or add to settings:

SUPABASE_URL = 'https://your-project-id.supabase.co'
SUPABASE_KEY = 'your-anon-public-key'
SUPABASE_BUCKET_NAME = 'your-supabase-bucket-name'

Files Not Uploading

Error: IOError: UPLOAD TO SUPABASE FAILED!

Solutions:

  1. Verify API credentials are correct
  2. Check bucket exists in Supabase
  3. Ensure bucket policies allow uploads
  4. Check network connectivity

Files Not Found

Error: FileNotFoundError: Failed to download file_name

Solutions:

  1. Verify file path is correct
  2. Check bucket name configuration
  3. Ensure file was successfully uploaded

Permission Denied

Error: IOError: Permission denied

Solutions:

  1. Go to Supabase Dashboard → Storage → Buckets
  2. Click the bucket → Policies
  3. Ensure public read access is enabled

Best Practices

  1. Use environment variables for sensitive credentials
  2. Set appropriate bucket policies (public read for media/static)
  3. Organize files with folders (avatars/, uploads/, etc.)
  4. Cache static files in CDN for better performance
  5. Monitor storage usage in Supabase dashboard
  6. Use Django's get_absolute_url() for model file URLs
  7. Use separate buckets for both static and media files

Support

For issues and questions:

License

MIT License - see LICENSE file for details.

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

django_supabase_storage-1.0.1.tar.gz (23.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_supabase_storage-1.0.1-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file django_supabase_storage-1.0.1.tar.gz.

File metadata

  • Download URL: django_supabase_storage-1.0.1.tar.gz
  • Upload date:
  • Size: 23.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_supabase_storage-1.0.1.tar.gz
Algorithm Hash digest
SHA256 474312baee5c8ecc7e8dda2eadd57ba6fee5a53ace00cdbf5fd91e23cc28bc0e
MD5 3e173174bb547729d34579231e0580aa
BLAKE2b-256 d6cc38dd0c9acd0ee7d8afc2585683d1f46759d28668e00c6b1b5ea176b234f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_supabase_storage-1.0.1.tar.gz:

Publisher: release.yml on Madhav89755/django-supabase-storage

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_supabase_storage-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_supabase_storage-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 55fce047109eec4d279aa79ad706f07b5b7629e532e4e22b9e081a08b21a07c6
MD5 6587a2cbc9649aefe549d04e0d947dd3
BLAKE2b-256 9f6b396980459b0ca5a9c51d2796ad992a7e30e67dad05f1a52ec404ebdd3b26

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_supabase_storage-1.0.1-py3-none-any.whl:

Publisher: release.yml on Madhav89755/django-supabase-storage

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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