├── Pipfile ├── README.md ├── app ├── main.py └── models.py ├── config.py └── db ├── __init__.py └── supabase.py /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | 8 | [dev-packages] 9 | 10 | [requires] 11 | python_version = "3.10" 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python Supabase Integration Guide 💡 2 | 3 | ![Blog Images](https://user-images.githubusercontent.com/33570148/219869662-c7c179f7-99a5-4cc3-8722-3b9096ae6feb.png) 4 | 5 | Learn how to integrate Supabase with FastAPI! 🚀 6 | 7 | ## Local setup 🎯 8 | 9 | - Clone the repository 10 | ``` 11 | git clone https://github.com/theinfosecguy/python-supabase-crud-api 12 | ``` 13 | 14 | - Change the directory 15 | ``` 16 | cd python-supabase-crud-api 17 | ``` 18 | 19 | - Update `api` and `url` in the `config.py` file. 20 | - Start the Virtual Environment using `pipenv shell` 21 | - Start the Uvicorn server using `uvicorn app.main:app --reload` 22 | 23 | 24 | ## Questions ⁉️ 25 | 26 | Feel free to create any issue or reach out to me via [email](mailto:hello@theinfosecguy.xyz). 27 | -------------------------------------------------------------------------------- /app/main.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | import bcrypt 4 | from fastapi import FastAPI 5 | from app.models import User 6 | from db.supabase import create_supabase_client 7 | 8 | app = FastAPI() 9 | 10 | # Initialize supabase client 11 | supabase = create_supabase_client() 12 | 13 | def user_exists(key: str = "email", value: str = None): 14 | user = supabase.from_("users").select("*").eq(key, value).execute() 15 | return len(user.data) > 0 16 | 17 | # Create a new user 18 | @app.post("/user") 19 | def create_user(user: User): 20 | try: 21 | # Convert email to lowercase 22 | user_email = user.email.lower() 23 | # Hash password 24 | hased_password = bcrypt.hashpw(user.password, bcrypt.gensalt()) 25 | 26 | # Check if user already exists 27 | if user_exists(value=user_email): 28 | return {"message": "User already exists"} 29 | 30 | # Add user to users table 31 | user = supabase.from_("users")\ 32 | .insert({"name": user.name, "email": user_email, "password": hased_password})\ 33 | .execute() 34 | 35 | # Check if user was added 36 | if user: 37 | return {"message": "User created successfully"} 38 | else: 39 | return {"message": "User creation failed"} 40 | except Exception as e: 41 | print("Error: ", e) 42 | return {"message": "User creation failed"} 43 | 44 | 45 | # Retrieve a user 46 | @app.get("/user") 47 | def get_user(user_id: Union[str, None] = None): 48 | try: 49 | if user_id: 50 | user = supabase.from_("users")\ 51 | .select("id", "name", "email")\ 52 | .eq("id", user_id)\ 53 | .execute() 54 | 55 | if user: 56 | return user 57 | else: 58 | users = supabase.from_("users")\ 59 | .select("id", "email", "name")\ 60 | .execute() 61 | if users: 62 | return users 63 | except Exception as e: 64 | print(f"Error: {e}") 65 | return {"message": "User not found"} 66 | 67 | 68 | # Update a user 69 | @app.put("/user") 70 | def update_user(user_id: str, email: str, name: str): 71 | try: 72 | user_email = email.lower() 73 | 74 | # Check if user exists 75 | if user_exists("id", user_id): 76 | # Check if email already exists 77 | email_exists = supabase.from_("users")\ 78 | .select("*").eq("email", user_email)\ 79 | .execute() 80 | if len(email_exists.data) > 0: 81 | return {"message": "Email already exists"} 82 | 83 | # Update user 84 | user = supabase.from_("users")\ 85 | .update({"name": name, "email": user_email})\ 86 | .eq("id", user_id).execute() 87 | if user: 88 | return {"message": "User updated successfully"} 89 | else: 90 | return {"message": "User update failed"} 91 | except Exception as e: 92 | print(f"Error: {e}") 93 | return {"message": "User update failed"} 94 | 95 | # Delete a user 96 | @app.delete("/user") 97 | def delete_user(user_id: str): 98 | try: 99 | # Check if user exists 100 | if user_exists("id", user_id): 101 | # Delete user 102 | supabase.from_("users")\ 103 | .delete().eq("id", user_id)\ 104 | .execute() 105 | return {"message": "User deleted successfully"} 106 | 107 | else: 108 | return {"message": "User deletion failed"} 109 | except Exception as e: 110 | print(f"Error: {e}") 111 | return {"message": "User deletion failed"} -------------------------------------------------------------------------------- /app/models.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class User(BaseModel): 4 | name: str 5 | email: str 6 | password: str -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | url="https://dummy.supabase.co" 2 | api="DUMMY API" -------------------------------------------------------------------------------- /db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theinfosecguy/python-supabase-crud-api/c2c1662c48c3dd9e539efa1fa1b2ef47f5d56765/db/__init__.py -------------------------------------------------------------------------------- /db/supabase.py: -------------------------------------------------------------------------------- 1 | from supabase import Client, create_client 2 | from config import api, url 3 | 4 | api_url: str = url 5 | key: str = api 6 | 7 | def create_supabase_client(): 8 | supabase: Client = create_client(url, key) 9 | return supabase --------------------------------------------------------------------------------