This guide walks you through integrating Firebase Storage with a Django project using the Firebase Admin SDK. It follows the exact configuration used in this codebase, so you can copy–paste safely.
- A custom Django storage backend powered by Firebase Storage.
- Environment-based toggle to switch between local file storage and Firebase Storage.
- Signed URLs and public URLs for serving files securely.
- Global delivery via Google’s infrastructure with low‑ops overhead.
- Simple Python SDK for uploads, signed URLs, and metadata.
- Flexible security using service accounts and IAM.
- Great for media (images, documents, avatars) with CDN‑friendly URLs.
Alternatives to consider: Amazon S3, Cloudflare R2, Supabase Storage, or the local filesystem for development.
- Python 3.12+
- Django 5.2+
- A Firebase project with a Storage bucket
- Service Account credentials for your Firebase project
Dependencies are already managed via pyproject.toml (includes firebase-admin and django-environ). If you prefer pip, see the commands below.
- Using pip
pip install firebase-admin django-environ- Using uv
uv add firebase-admin django-environ- Go to Google Cloud Console → IAM & Admin → Service Accounts → Create key.
- Choose JSON and download the file.
- You’ll copy values from this JSON into environment variables (see below).
Important fields (names match your settings.py):
project_idprivate_key_idprivate_key(keep secure, replace literal newlines with \n in.env)client_emailclient_id- Your Firebase Storage bucket name (e.g.,
my-project.appspot.com)
Create or update your .env file at the project root:
USE_FIREBASE_STORAGE=True
FIREBASE_STORAGE_BUCKET=<bucket_name>
FIREBASE_PROJECT_ID=<project_id>
FIREBASE_PRIVATE_KEY_ID=<private_key_id>
FIREBASE_PRIVATE_KEY=<private_key_from_service_account>
FIREBASE_CLIENT_EMAIL=<client_email_from_service_account>
FIREBASE_CLIENT_ID=<client_id_from_service_account>Notes:
- If your private key contains actual newlines, replace them with
\nin.env. - Set
USE_FIREBASE_STORAGE=Falselocally if you prefer filesystem storage.
Your settings.py already includes the required configuration using django-environ and a conditional DEFAULT_FILE_STORAGE switch. Key parts:
# Base toggle and credentials
USE_FIREBASE_STORAGE = env.bool('USE_FIREBASE_STORAGE', default=False)
FIREBASE_STORAGE_BUCKET = env.str('FIREBASE_STORAGE_BUCKET', default='')
FIREBASE_PROJECT_ID = env.str('FIREBASE_PROJECT_ID', default='')
FIREBASE_PRIVATE_KEY_ID = env.str('FIREBASE_PRIVATE_KEY_ID', default='')
FIREBASE_PRIVATE_KEY = env.str('FIREBASE_PRIVATE_KEY', default='')
FIREBASE_CLIENT_EMAIL = env.str('FIREBASE_CLIENT_EMAIL', default='')
FIREBASE_CLIENT_ID = env.str('FIREBASE_CLIENT_ID', default='')
if USE_FIREBASE_STORAGE and FIREBASE_STORAGE_BUCKET:
DEFAULT_FILE_STORAGE = 'app_storages.firebase_storage.FirebaseStorage'
STORAGES = {
'default': {
'BACKEND': DEFAULT_FILE_STORAGE
},
}This means when USE_FIREBASE_STORAGE=True and a bucket is provided, Django’s default storage becomes the custom Firebase backend.
Create app_storages/firebase_storage.py (already present in this repo). It defines a deconstructible class FirebaseStorage that:
- Initializes the Firebase Admin SDK from env vars
- Uploads files to your bucket
- Generates signed URLs via
generate_signed_url - Supports
exists,delete,listdir,size, and time metadata helpers
Key behaviors to know:
_savemakes uploaded files public by default usingblob.make_public().url(name)andsigned_url(name)can return short-lived access URLs.- Helper
firebase_upload_path(instance, filename)builds date-based paths:storage/<model>/<YYYY>/<MM>/<DD>/<filename>.
If Firebase storage is the default, you can use ImageField or FileField as usual.
Example using the provided firebase_upload_path helper:
from django.db import models
from app_storages.firebase_storage import firebase_upload_path
class Profile(models.Model):
avatar = models.ImageField(upload_to=firebase_upload_path, blank=True, null=True)When USE_FIREBASE_STORAGE=True, files uploaded via admin, forms, or DRF will go to Firebase Storage automatically.
from django.core.files.storage import default_storage
def save_bytes(path: str, data: bytes, content_type: str | None = None):
# path example: "uploads/docs/readme.txt"
name = default_storage.save(path, data)
url = default_storage.url(name)
return name, urlFor signed access:
from app_storages.firebase_storage import get_firebase_storage
storage = get_firebase_storage()
signed = storage.signed_url('path/in/bucket.ext', expiration=3600) # 1 hour- Local development: set
USE_FIREBASE_STORAGE=Falseto store files on the local filesystem (mediafiles/). - Production: set
USE_FIREBASE_STORAGE=Truewith valid Firebase env vars. - Static files are still served by WhiteNoise in this project; Firebase is for user-uploaded media.
- Never commit raw service account JSON or secrets to version control.
- Restrict your service account permissions to only what’s needed for Storage.
- Prefer signed URLs over public blobs for private assets.
- Rotate keys if they’re exposed.
-
Files not uploading
- Check
USE_FIREBASE_STORAGEandFIREBASE_STORAGE_BUCKETvalues. - Verify private key formatting. In
.env, newlines must be\n. - Confirm the bucket exists and your service account has access.
- Check
-
Getting permission errors
- Ensure the service account has
Storage Object Adminon the bucket.
- Ensure the service account has
-
Wrong URLs or 404s
- Ensure the blob path matches your
upload_tologic. - For signed URLs, ensure system time is correct and
expirationis in the future.
- Ensure the blob path matches your
- Name: Your Name
- Portfolio: https://your-portfolio.example.com
- GitHub: https://github.com/your-handle
- LinkedIn: https://www.linkedin.com/in/your-handle/
- X (Twitter): https://x.com/your-handle
- Email: [email protected]
Tip: Replace the image path and links above with your actual assets. For a square avatar, use 256×256 or 512×512.
- Firebase Admin SDK (Python): https://firebase.google.com/docs/admin/setup
- Google Cloud Storage Python Client: https://cloud.google.com/python/docs/reference/storage/latest
- Django File Storage: https://docs.djangoproject.com/en/stable/topics/files/
- Install
firebase-adminanddjango-environ - Add
.envwith Firebase credentials andUSE_FIREBASE_STORAGE=True - Ensure
app_storages.FirebaseStorageis active viasettings.py - Use
upload_to=firebase_upload_pathin your models (optional but recommended) - Deploy and test an upload (admin/DRF/form)
