Asynchronous Python ODM for MongoDB with modern Pydantic-based document mapping
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Database and ODM initialization functionality that establishes connections, registers document models, creates indexes, and configures the Beanie ODM for use in applications.
The primary function for initializing Beanie with database connections and document model registration.
async def init_beanie(
database: Optional[Any] = None,
document_models: List[Union[Type[Document], Type[View], str, Dict]] = None,
connection_string: Optional[str] = None,
allow_index_dropping: bool = False,
recreate_views: bool = False,
skip_indexes: bool = False,
multiprocessing_mode: bool = False
) -> None:
"""
Initialize Beanie ODM with database connection and document models.
Args:
database: Motor database instance or database name
document_models: List of document classes to register
connection_string: MongoDB connection string (alternative to database)
allow_index_dropping: Allow dropping indexes during initialization
recreate_views: Recreate views if they already exist
skip_indexes: Skip index creation during initialization
multiprocessing_mode: Enable multiprocessing compatibility mode
Raises:
ConfigurationError: If configuration is invalid
ConnectionError: If database connection fails
"""import asyncio
from beanie import Document, View, init_beanie
from motor.motor_asyncio import AsyncIOMotorClient
# Define document models
class User(Document):
name: str
email: str
class Settings:
collection = "users"
class Post(Document):
title: str
content: str
author_id: str
class Settings:
collection = "posts"
class UserStatsView(View):
user_id: str
post_count: int
class Settings:
source = Post
pipeline = [
{"$group": {"_id": "$author_id", "post_count": {"$sum": 1}}},
{"$project": {"user_id": "$_id", "post_count": 1, "_id": 0}}
]
# Method 1: Using Motor client and database
async def init_with_client():
client = AsyncIOMotorClient("mongodb://localhost:27017")
database = client.myapp
await init_beanie(
database=database,
document_models=[User, Post, UserStatsView]
)
# Method 2: Using connection string
async def init_with_connection_string():
await init_beanie(
connection_string="mongodb://localhost:27017/myapp",
document_models=[User, Post, UserStatsView]
)
# Method 3: With additional options
async def init_with_options():
client = AsyncIOMotorClient("mongodb://localhost:27017")
database = client.myapp
await init_beanie(
database=database,
document_models=[User, Post, UserStatsView],
allow_index_dropping=True, # Allow index modifications
recreate_views=True, # Recreate views if they exist
skip_indexes=False # Create indexes (default)
)
# Method 4: Using string references (for avoiding circular imports)
async def init_with_string_refs():
await init_beanie(
connection_string="mongodb://localhost:27017/myapp",
document_models=[
"myapp.models.User",
"myapp.models.Post",
"myapp.views.UserStatsView"
]
)
# Method 5: Mixed configuration with model dictionaries
async def init_with_mixed_config():
await init_beanie(
connection_string="mongodb://localhost:27017/myapp",
document_models=[
User, # Direct class reference
"myapp.models.Post", # String reference
{ # Dictionary configuration
"model": UserStatsView,
"recreate": True
}
]
)import os
from beanie import init_beanie
from motor.motor_asyncio import AsyncIOMotorClient
# Environment-based configuration
async def init_production():
# Read from environment variables
mongodb_url = os.getenv("MONGODB_URL", "mongodb://localhost:27017")
database_name = os.getenv("DATABASE_NAME", "production")
# Configure client with production settings
client = AsyncIOMotorClient(
mongodb_url,
maxPoolSize=50,
minPoolSize=10,
maxIdleTimeMS=30000,
serverSelectionTimeoutMS=5000,
connectTimeoutMS=10000,
socketTimeoutMS=20000
)
database = client[database_name]
# Import all models
from myapp.models import User, Post, Comment, Category
from myapp.views import PostStatsView, UserActivityView
await init_beanie(
database=database,
document_models=[
User, Post, Comment, Category,
PostStatsView, UserActivityView
],
allow_index_dropping=False, # Prevent accidental index drops
recreate_views=False, # Don't recreate existing views
skip_indexes=False # Ensure indexes are created
)
# FastAPI integration
from fastapi import FastAPI
app = FastAPI()
@app.on_event("startup")
async def startup_event():
await init_production()
@app.on_event("shutdown")
async def shutdown_event():
# Close database connections
client = AsyncIOMotorClient.get_default_client()
if client:
client.close()from beanie import init_beanie
from beanie.exceptions import ConfigurationError
from pymongo.errors import ConnectionFailure, ServerSelectionTimeoutError
async def safe_init():
try:
await init_beanie(
connection_string="mongodb://localhost:27017/myapp",
document_models=[User, Post]
)
print("Beanie initialized successfully")
except ConfigurationError as e:
print(f"Configuration error: {e}")
# Handle invalid model configuration
except ConnectionFailure as e:
print(f"Database connection failed: {e}")
# Handle connection issues
except ServerSelectionTimeoutError as e:
print(f"Server selection timeout: {e}")
# Handle timeout issues
except Exception as e:
print(f"Unexpected error during initialization: {e}")
# Handle other errors# Custom initialization with advanced features
async def init_advanced():
from motor.motor_asyncio import AsyncIOMotorClient
# Configure client with SSL and authentication
client = AsyncIOMotorClient(
"mongodb://username:password@cluster.mongodb.net/",
tls=True,
tlsCAFile="ca-cert.pem",
tlsCertificateKeyFile="client-cert.pem",
authSource="admin",
replicaSet="myReplicaSet"
)
database = client.production
# Initialize with multiprocessing support
await init_beanie(
database=database,
document_models=[User, Post, Comment],
multiprocessing_mode=True, # Enable for multiprocessing apps
allow_index_dropping=True, # Allow index management
recreate_views=True # Refresh views on startup
)
# Testing setup with in-memory database
async def init_testing():
from mongomock_motor import AsyncMongoMockClient
# Use mock client for testing
client = AsyncMongoMockClient()
database = client.test_db
await init_beanie(
database=database,
document_models=[User, Post],
skip_indexes=True # Skip index creation in tests
)from typing import Optional, List, Union, Dict, Any, Type
from motor.motor_asyncio import AsyncIOMotorDatabase
# Document model types
DocumentModel = Union[Type[Document], Type[View], str, Dict[str, Any]]
DocumentModels = List[DocumentModel]
# Database connection types
DatabaseType = Union[AsyncIOMotorDatabase, str]
ConnectionString = str
# Configuration options
InitOptions = Dict[str, Any]Install with Tessl CLI
npx tessl i tessl/pypi-beanie