Initial commit
This commit is contained in:
343
README.md
Normal file
343
README.md
Normal file
@@ -0,0 +1,343 @@
|
||||
# Supabase Connector
|
||||
|
||||
Простой и удобный Python коннектор для работы с [Supabase](https://supabase.com).
|
||||
|
||||
## 🎯 О проекте
|
||||
|
||||
Этот проект предоставляет удобную обертку над официальным Python клиентом Supabase, упрощая базовые операции с базой данных и Storage.
|
||||
|
||||
## ✨ Возможности
|
||||
|
||||
- ✅ Простое подключение к Supabase через переменные окружения
|
||||
- 📊 CRUD операции (Create, Read, Update, Delete)
|
||||
- 🔍 Фильтрация и лимитирование результатов
|
||||
- 📦 Работа с Supabase Storage
|
||||
- 🛡️ Обработка ошибок
|
||||
- 🎨 Чистый и понятный API
|
||||
|
||||
## 📋 Требования
|
||||
|
||||
- Python 3.8+
|
||||
- Аккаунт Supabase (бесплатный или платный)
|
||||
|
||||
## 🚀 Установка
|
||||
|
||||
### Вариант 1: Клонирование репозитория
|
||||
|
||||
```bash
|
||||
git clone https://github.com/yourusername/supabase-connector.git
|
||||
cd supabase-connector
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Вариант 2: Установка как пакет (в разработке)
|
||||
|
||||
```bash
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
## ⚙️ Настройка
|
||||
|
||||
1. Создайте файл `.env` в корне проекта:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
2. Заполните данными из вашего Supabase проекта:
|
||||
|
||||
```env
|
||||
SUPABASE_URL=https://your-project-id.supabase.co
|
||||
SUPABASE_KEY=your_anon_key
|
||||
```
|
||||
|
||||
**Где найти эти данные:**
|
||||
1. Откройте [Supabase Dashboard](https://app.supabase.com)
|
||||
2. Выберите ваш проект
|
||||
3. Перейдите в Settings → API
|
||||
4. Скопируйте **Project URL** и **anon/public key**
|
||||
|
||||
## 📖 Использование
|
||||
|
||||
### Базовый пример
|
||||
|
||||
```python
|
||||
from supabase import SupabaseManager
|
||||
|
||||
# Инициализация
|
||||
sb = SupabaseManager()
|
||||
|
||||
# Получение данных
|
||||
users = sb.select(table="users", limit=10)
|
||||
print(f"Найдено пользователей: {len(users)}")
|
||||
|
||||
# Добавление записи
|
||||
new_user = sb.insert(
|
||||
table="users",
|
||||
data={
|
||||
"name": "Тимур",
|
||||
"email": "timur@example.com",
|
||||
"age": 28
|
||||
}
|
||||
)
|
||||
print(f"Создан пользователь с ID: {new_user.get('id')}")
|
||||
```
|
||||
|
||||
### Фильтрация данных
|
||||
|
||||
```python
|
||||
# Получить пользователей с определенным возрастом
|
||||
users_30 = sb.select(
|
||||
table="users",
|
||||
filters={"age": 30}
|
||||
)
|
||||
|
||||
# Получить только имена и email
|
||||
users = sb.select(
|
||||
table="users",
|
||||
columns="name, email",
|
||||
limit=5
|
||||
)
|
||||
```
|
||||
|
||||
### Обновление записей
|
||||
|
||||
```python
|
||||
# Обновить возраст пользователя с ID=1
|
||||
updated = sb.update(
|
||||
table="users",
|
||||
data={"age": 31},
|
||||
filters={"id": 1}
|
||||
)
|
||||
```
|
||||
|
||||
### Удаление записей
|
||||
|
||||
```python
|
||||
# Удалить пользователя с ID=1
|
||||
deleted = sb.delete(
|
||||
table="users",
|
||||
filters={"id": 1}
|
||||
)
|
||||
```
|
||||
|
||||
### Работа с Storage
|
||||
|
||||
```python
|
||||
# Загрузить файл
|
||||
with open("avatar.png", "rb") as f:
|
||||
file_data = f.read()
|
||||
|
||||
sb.upload_file(
|
||||
bucket="avatars",
|
||||
file_path="user_123/avatar.png",
|
||||
file_data=file_data,
|
||||
content_type="image/png"
|
||||
)
|
||||
|
||||
# Получить публичный URL
|
||||
url = sb.get_public_url(
|
||||
bucket="avatars",
|
||||
file_path="user_123/avatar.png"
|
||||
)
|
||||
print(f"Файл доступен по адресу: {url}")
|
||||
```
|
||||
|
||||
### Продвинутые запросы
|
||||
|
||||
Для сложных запросов используйте прямой доступ к клиенту:
|
||||
|
||||
```python
|
||||
client = sb.get_client()
|
||||
|
||||
# Запрос с операторами сравнения
|
||||
adults = client.table("users")\
|
||||
.select("*")\
|
||||
.gte("age", 18)\
|
||||
.order("age", desc=True)\
|
||||
.execute()
|
||||
|
||||
# Поиск по паттерну
|
||||
ivan_users = client.table("users")\
|
||||
.select("*")\
|
||||
.ilike("name", "%иван%")\
|
||||
.execute()
|
||||
```
|
||||
|
||||
## 📁 Структура проекта
|
||||
|
||||
```
|
||||
supabase-connector/
|
||||
├── supabase.py # Основной класс SupabaseManager
|
||||
├── __init__.py # Инициализация пакета
|
||||
├── example.py # Примеры использования
|
||||
├── requirements.txt # Зависимости
|
||||
├── setup.py # Настройка пакета
|
||||
├── .env.example # Шаблон конфигурации
|
||||
├── .gitignore # Исключения для git
|
||||
└── README.md # Документация
|
||||
```
|
||||
|
||||
## 🧪 Запуск примеров
|
||||
|
||||
В файле `example.py` находятся готовые примеры использования:
|
||||
|
||||
```bash
|
||||
python example.py
|
||||
```
|
||||
|
||||
Раскомментируйте нужные примеры в функции `main()`.
|
||||
|
||||
## 📝 API Reference
|
||||
|
||||
### SupabaseManager
|
||||
|
||||
#### `__init__()`
|
||||
Инициализирует подключение к Supabase, используя переменные окружения.
|
||||
|
||||
#### `select(table, columns="*", filters=None, limit=None)`
|
||||
Выполняет SELECT запрос.
|
||||
|
||||
**Параметры:**
|
||||
- `table` (str): Название таблицы
|
||||
- `columns` (str): Колонки для выборки
|
||||
- `filters` (dict): Словарь с фильтрами `{column: value}`
|
||||
- `limit` (int): Максимальное количество записей
|
||||
|
||||
**Возвращает:** `List[Dict]`
|
||||
|
||||
#### `insert(table, data)`
|
||||
Вставляет новую запись.
|
||||
|
||||
**Параметры:**
|
||||
- `table` (str): Название таблицы
|
||||
- `data` (dict): Данные для вставки
|
||||
|
||||
**Возвращает:** `Dict`
|
||||
|
||||
#### `update(table, data, filters)`
|
||||
Обновляет записи.
|
||||
|
||||
**Параметры:**
|
||||
- `table` (str): Название таблицы
|
||||
- `data` (dict): Данные для обновления
|
||||
- `filters` (dict): Фильтры `{column: value}`
|
||||
|
||||
**Возвращает:** `List[Dict]`
|
||||
|
||||
#### `delete(table, filters)`
|
||||
Удаляет записи.
|
||||
|
||||
**Параметры:**
|
||||
- `table` (str): Название таблицы
|
||||
- `filters` (dict): Фильтры `{column: value}`
|
||||
|
||||
**Возвращает:** `List[Dict]`
|
||||
|
||||
#### `upload_file(bucket, file_path, file_data, content_type=None)`
|
||||
Загружает файл в Storage.
|
||||
|
||||
**Параметры:**
|
||||
- `bucket` (str): Название bucket
|
||||
- `file_path` (str): Путь к файлу в bucket
|
||||
- `file_data` (bytes): Данные файла
|
||||
- `content_type` (str): MIME тип файла
|
||||
|
||||
**Возвращает:** `bool`
|
||||
|
||||
#### `get_public_url(bucket, file_path)`
|
||||
Получает публичный URL файла.
|
||||
|
||||
**Параметры:**
|
||||
- `bucket` (str): Название bucket
|
||||
- `file_path` (str): Путь к файлу
|
||||
|
||||
**Возвращает:** `str`
|
||||
|
||||
#### `get_client()`
|
||||
Возвращает прямой доступ к клиенту Supabase для сложных операций.
|
||||
|
||||
**Возвращает:** `Client`
|
||||
|
||||
## 🧪 Создание тестовой таблицы
|
||||
|
||||
Для тестирования создайте таблицу в Supabase:
|
||||
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
age INTEGER,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Тестовые данные
|
||||
INSERT INTO users (name, email, age) VALUES
|
||||
('Иван Иванов', 'ivan@example.com', 30),
|
||||
('Мария Петрова', 'maria@example.com', 25),
|
||||
('Алексей Сидоров', 'alex@example.com', 35);
|
||||
```
|
||||
|
||||
## 🔐 Безопасность
|
||||
|
||||
- ⚠️ Никогда не коммитьте файл `.env` в git
|
||||
- Используйте **anon key** для клиентских операций
|
||||
- Настройте Row Level Security (RLS) в Supabase
|
||||
- Для серверных операций используйте **service_role key** с осторожностью
|
||||
|
||||
## 🛠️ Расширение функциональности
|
||||
|
||||
Вы можете легко добавить свои методы в класс `SupabaseManager`:
|
||||
|
||||
```python
|
||||
class SupabaseManager:
|
||||
# ... существующие методы ...
|
||||
|
||||
def count_records(self, table: str) -> int:
|
||||
"""Подсчет количества записей в таблице"""
|
||||
data = self.select(table=table)
|
||||
return len(data)
|
||||
|
||||
def search_by_text(self, table: str, column: str, search_term: str):
|
||||
"""Полнотекстовый поиск"""
|
||||
return self.client.table(table)\
|
||||
.select("*")\
|
||||
.ilike(column, f"%{search_term}%")\
|
||||
.execute().data
|
||||
```
|
||||
|
||||
## 🐛 Решение проблем
|
||||
|
||||
### Ошибка подключения
|
||||
```
|
||||
ValueError: SUPABASE_URL и SUPABASE_KEY должны быть установлены
|
||||
```
|
||||
**Решение:** Проверьте файл `.env` и убедитесь, что указаны правильные значения.
|
||||
|
||||
### Ошибка доступа к таблице
|
||||
```
|
||||
Ошибка при выполнении SELECT: ...
|
||||
```
|
||||
**Решение:**
|
||||
1. Убедитесь, что таблица существует
|
||||
2. Проверьте настройки RLS (Row Level Security)
|
||||
3. Убедитесь, что у вашего ключа есть доступ к таблице
|
||||
|
||||
## 📚 Дополнительные ресурсы
|
||||
|
||||
- [Официальная документация Supabase](https://supabase.com/docs)
|
||||
- [Supabase Python Client](https://supabase.com/docs/reference/python/introduction)
|
||||
- [Row Level Security](https://supabase.com/docs/guides/auth/row-level-security)
|
||||
|
||||
## 🤝 Вклад в проект
|
||||
|
||||
Приветствуются любые предложения и улучшения! Создавайте Issues и Pull Requests.
|
||||
|
||||
## 📄 Лицензия
|
||||
|
||||
MIT License - используйте свободно в своих проектах.
|
||||
|
||||
## ⭐ Поддержка
|
||||
|
||||
Если проект был полезен, поставьте звезду на GitHub!
|
||||
Reference in New Issue
Block a user