Bunnet - Synchronous Python ODM for MongoDB

1.3.0 · active · verified Thu Apr 16

Bunnet is a synchronous Python Object-Document Mapper (ODM) for MongoDB, built upon Pydantic for data modeling. It simplifies interaction with MongoDB collections by mapping Python classes to documents, reducing boilerplate code for common database operations like adding, updating, and deleting. Bunnet is a synchronous fork of the popular Beanie ODM, and its current version is 1.3.0 with active development and maintenance.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to connect to MongoDB, define a Bunnet Document, insert data, and perform basic queries and updates. It uses Pydantic for defining nested data structures and `pymongo.MongoClient` for the underlying database connection. Remember to replace `mongodb://localhost:27017` and `your_db_name` with your actual MongoDB connection string and database name.

from typing import Optional
from pymongo import MongoClient
from pydantic import BaseModel
from bunnet import Document, Indexed, init_bunnet
import os

# Define a Pydantic model for a nested object
class Category(BaseModel):
    name: str
    description: str

# Define a Bunnet Document model
class Product(Document):
    name: str
    description: Optional[str] = None
    price: Indexed(float)
    category: Category

    # Optional: Configure collection name and other settings
    class Settings:
        name = "products_collection"

async def main():
    # Connect to MongoDB (replace with your connection string)
    # Use os.environ.get for secure credentials in production
    MONGO_DETAILS = os.environ.get('MONGO_URI', 'mongodb://localhost:27017')
    client = MongoClient(MONGO_DETAILS)

    # Initialize Bunnet with the database and document models
    # Ensure 'your_db_name' exists or will be created upon first write
    init_bunnet(database=client.get_database('your_db_name'), document_models=[Product])

    # Create a category instance
    chocolate_category = Category(name="Chocolate", description="A preparation of roasted and ground cacao seeds.")

    # Create a product instance
    tonybar = Product(name="Tony's Chocolonely", price=5.95, category=chocolate_category)

    # Insert the document into the database
    inserted_product = tonybar.insert()
    print(f"Inserted product: {inserted_product.name}")

    # Find a document using Pythonic syntax
    found_product = Product.find_one(Product.price < 10).run()
    if found_product:
        print(f"Found product: {found_product.name}")

    # Update a document
    updated_product = found_product.set({Product.name: "Gold Bar"})
    print(f"Updated product to: {updated_product.name}")

if __name__ == "__main__":
    # Bunnet is synchronous, so no asyncio.run() needed directly for document operations.
    # The main function is defined as async only for consistency if a project mixed sync/async components
    # For this quickstart, you would typically run the synchronous operations directly.
    # However, to simulate an async context often seen in examples for its counterpart (Beanie),
    # we wrap it here. For a purely synchronous application, you'd call main() directly and remove 'async/await'.
    main()

view raw JSON →