PostgREST Client for Python
The `postgrest` library provides an ORM-like interface for interacting with PostgREST APIs from Python. It supports both synchronous and asynchronous operations, allowing developers to easily query, insert, update, and delete data, as well as call stored procedures. The library is actively maintained, currently at version 2.28.3, and has a consistent release cadence with frequent updates.
Warnings
- breaking The behavior of the `.schema()` method changed in version 1.0.0. It now persists only for the current query builder instance and does not affect subsequent queries on the client or other query builders.
- breaking A 'minor breaking change' was noted for users integrating with `supabase_auth` around version 2.24.0. While not directly in the `postgrest` library itself, it indicates potential compatibility issues for Supabase users.
- gotcha The library offers both `AsyncPostgrestClient` and `SyncPostgrestClient`. Mixing asynchronous and synchronous code incorrectly (e.g., calling `await` on a `SyncPostgrestClient` method or blocking an event loop with `SyncPostgrestClient` in an async context) will lead to errors or performance issues.
- gotcha Responses from `execute()` contain the data in the `.data` attribute. Direct access to the response object might not yield the expected results if not correctly parsing the structure.
Install
-
pip install postgrest
Imports
- AsyncPostgrestClient
from postgrest import AsyncPostgrestClient
- SyncPostgrestClient
from postgrest import SyncPostgrestClient
Quickstart
import asyncio
import os
from postgrest import AsyncPostgrestClient
# Replace with your PostgREST URL and (optional) API key
POSTGREST_URL = os.environ.get('POSTGREST_URL', 'http://localhost:3000')
# BEARER_TOKEN = os.environ.get('POSTGREST_TOKEN', 'YOUR_API_KEY') # Optional, if authentication is required
async def main():
# headers = {'Authorization': f'Bearer {BEARER_TOKEN}'} if BEARER_TOKEN else {}
headers = {}
async with AsyncPostgrestClient(POSTGREST_URL, headers=headers) as client:
try:
# Example: Insert data
print('Inserting a new country...')
insert_result = await client.from_('countries').insert({'name': 'Exampleland', 'capital': 'Example City'}).execute()
print(f'Insert successful: {insert_result.data}')
# Example: Read data
print('Fetching countries...')
response = await client.from_('countries').select('id', 'name', 'capital').limit(5).execute()
print('Fetched countries:')
for country in response.data:
print(f" ID: {country['id']}, Name: {country['name']}, Capital: {country['capital']}")
# Example: Update data
print('Updating Exampleland...')
update_result = await client.from_('countries').update({'capital': 'New Example City'}).eq('name', 'Exampleland').execute()
print(f'Update successful: {update_result.data}')
# Example: Delete data
print('Deleting Exampleland...')
delete_result = await client.from_('countries').delete().eq('name', 'Exampleland').execute()
print(f'Delete successful: {delete_result.data}')
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == '__main__':
asyncio.run(main())