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

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.0.tar.gz (25.5 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.0-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: django_supabase_storage-1.0.0.tar.gz
  • Upload date:
  • Size: 25.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for django_supabase_storage-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3f691f3d99296626471ad94a607cdc79af546f592904d0fd46c91f44eef87834
MD5 4347466542ac1788c451cf21a7cea6f3
BLAKE2b-256 d4dbb76d6d3d3290580c57679c243138312f1a05be9c694b6f652bd21a252d21

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_supabase_storage-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 277b0c8c66cf089b48a1debd788c25e8f898f0788c75286e16f1adffd74fb167
MD5 d7c064859b9fc200f5703df9c425fabd
BLAKE2b-256 8c2f1dc6064614b4ac7ca6620fee9c1efa13d6100e1a728fa2051a87deff1508

See more details on using hashes here.

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