A Python ORM (Object-Relational Mapper) for PocketBase that provides Pydantic model integration and automatic schema synchronization.
- 🚀 Pydantic model integration for data validation and serialization
- 🔄 Automatic schema synchronization with PocketBase collections
- 📦 Support for most PocketBase field types including relations and file uploads
- 🛠️ Simple and intuitive API for CRUD operations
uv install pocketbase-orm
from pocketbase_orm import PBModel
from pydantic import EmailStr, AnyUrl, Field
from datetime import datetime, timezone
from pocketbase.client import FileUpload
# Define your models
class RelatedModel(PBModel, collection="related_models"): # Optionally specify collection name
name: str
class Example(PBModel): # Collection name will be "examples" by default
text_field: str
number_field: int
is_active: bool
url_field: AnyUrl
created_at: datetime
options: list[str]
email_field: EmailStr | None = None
related_model: RelatedModel | str = Field(..., description="Related model reference")
image: FileUpload | str = Field(..., description="Image file upload")
# Initialize PocketBase client and bind it to the ORM
client = PBModel.init_client(
"YOUR_POCKETBASE_URL",
"[email protected]",
"password"
)
# Sync collection schemas
RelatedModel.sync_collection()
Example.sync_collection()
# Create and save records
related_model = RelatedModel(name="Related Model")
related_model.save()
# Create a new record with file upload
with open("image.png", "rb") as f:
example = Example(
text_field="Test with image",
number_field=123,
is_active=True,
email_field="[email protected]",
url_field="http://example.com",
created_at=datetime.now(timezone.utc),
options=["option1", "option2"],
related_model=related_model.id,
image=FileUpload(("image.png", f))
)
example.save()
# Query records
full_list = Example.get_full_list()
one = Example.get_one("RECORD_ID")
first = Example.get_first_list_item(filter='email_field = "[email protected]"')
filtered_list = Example.get_list(filter='email_field = "[email protected]"')
# Get file contents
image_bytes = example.get_file_contents("image")
Models inherit from PBModel
and use Pydantic field types:
from enum import Enum
class UserType(str, Enum):
ADMIN = "admin"
REGULAR = "regular"
GUEST = "guest"
class MyModel(PBModel, collection="my_models"): # Specify custom collection name
name: str
age: int
email: EmailStr | None = None
user_type: UserType # Will be created as a select field in PocketBase
The collection name will be automatically derived from the class name (pluralized) if not specified using the collection
parameter when subclassing PBModel
.
- Text:
str
- Number:
int
,float
- Boolean:
bool
- Email:
EmailStr
- URL:
AnyUrl
- DateTime:
datetime
- JSON:
List
,Dict
- File:
FileUpload | str
- Relation:
Union[RelatedModel, str]
- Select:
Enum
bind_client(client: PocketBase)
: Bind PocketBase client to the model classsync_collection()
: Create or update the collection schema in PocketBasedelete_collection()
: Delete the entire collection from PocketBaseget_one(id: str, **kwargs) -> T
: Get a single record by IDget_list(*args, **kwargs) -> List[T]
: Get a paginated list of recordsget_full_list(*args, **kwargs) -> List[T]
: Get all recordsget_first_list_item(*args, **kwargs) -> T
: Get the first matching recorddelete_by_id(id: str, **kwargs)
: Delete a record by ID
save() -> T
: Create or update the recorddelete()
: Delete the current recordget_file_contents(field: str) -> bytes
: Get the contents of a file field
- The ORM currently supports basic CRUD operations and schema synchronization
- Complex queries should use the PocketBase client directly
- Relationship handling is limited to single relations
- Indexes must be created manually
- Schemas need to be updated manually until this issue is resolved
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.