Skip to main content

Supabase Django integration

· 5 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

Supabase Integration with Django

Here's a guide to integrating Supabase with a Django application. We will use the requests library to make API calls to Supabase, as there is no official Django-specific Supabase ORM.

Set Up Your Supabase Project

First, you need a Supabase project.

  1. Go to the Supabase Dashboard.
  2. Create a new project.
  3. Navigate to API Settings to find your Project URL and anon public key. You will use these in your Django settings.
  4. Create a test table, for example, products, with a few columns like id (primary key), name, and price.

Set Up Your Django Project

Next, set up a new Django project and a virtual environment.

# Create a virtual environment
python3 -m venv venv
source venv/bin/activate

# Install Django and the requests library
pip install Django requests

Create a new Django project and app:

django-admin startproject myproject
cd myproject
python manage.py startapp products

In myproject/settings.py, add your new products app and your Supabase credentials. It's crucial to use environment variables for sensitive data in a production environment.

# myproject/settings.py

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'products', # Your new app
]

# Supabase Credentials
SUPABASE_URL = os.environ.get("SUPABASE_URL", "https://your-project-ref.supabase.co")
SUPABASE_KEY = os.environ.get("SUPABASE_KEY", "eyJhbGciOiJIUzI1NiIsIn...")

Create a Supabase API Wrapper

To keep your code clean, create a simple wrapper for Supabase API calls. In your products app, create a file named supabase_client.py.

# products/supabase_client.py

import os
import requests

SUPABASE_URL = os.environ.get("SUPABASE_URL")
SUPABASE_KEY = os.environ.get("SUPABASE_KEY")

class SupabaseClient:
def __init__(self, table_name):
self.url = f"{SUPABASE_URL}/rest/v1/{table_name}"
self.headers = {
"apikey": SUPABASE_KEY,
"Authorization": f"Bearer {SUPABASE_KEY}",
"Content-Type": "application/json"
}

def get_all(self):
response = requests.get(self.url, headers=self.headers)
response.raise_for_status()
return response.json()

def get_by_id(self, item_id):
response = requests.get(f"{self.url}?id=eq.{item_id}", headers=self.headers)
response.raise_for_status()
return response.json()

def create(self, data):
response = requests.post(self.url, json=data, headers=self.headers)
response.raise_for_status()
return response.json()

def update(self, item_id, data):
response = requests.patch(f"{self.url}?id=eq.{item_id}", json=data, headers=self.headers)
response.raise_for_status()
return response.json()

def delete(self, item_id):
response = requests.delete(f"{self.url}?id=eq.{item_id}", headers=self.headers)
response.raise_for_status()
return response.json()

Create Views and URLs

Now, create your views in products/views.py to use the client wrapper.

# products/views.py

from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from .supabase_client import SupabaseClient
import json

product_client = SupabaseClient("products")

@require_http_methods(["GET", "POST"])
def product_list_create(request):
if request.method == "GET":
products = product_client.get_all()
return JsonResponse(products, safe=False)

elif request.method == "POST":
data = json.loads(request.body)
new_product = product_client.create(data)
return JsonResponse(new_product, status=201, safe=False)

@require_http_methods(["GET", "PUT", "DELETE"])
def product_detail(request, product_id):
if request.method == "GET":
product = product_client.get_by_id(product_id)
if product:
return JsonResponse(product[0], safe=False)
return JsonResponse({"error": "Product not found"}, status=404)

elif request.method == "PUT":
data = json.loads(request.body)
updated_product = product_client.update(product_id, data)
if updated_product:
return JsonResponse(updated_product[0], safe=False)
return JsonResponse({"error": "Product not found"}, status=404)

elif request.method == "DELETE":
product_client.delete(product_id)
return JsonResponse({"message": f"Product with ID {product_id} deleted"}, status=200)

Finally, create a products/urls.py file to define your endpoints and include them in your main myproject/urls.py file.

# products/urls.py

from django.urls import path
from . import views

urlpatterns = [
path("products/", views.product_list_create),
path("products/<int:product_id>/", views.product_detail),
]
# myproject/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('products.urls')),
]