8000 migrate beanie to barebones motor + pydantic setup · Issue #105 · hospitaljobsin/hospitaljobsin · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
migrate beanie to barebones motor + pydantic setup #105
Open
@aryaniyaps

Description

@aryaniyaps

beanie has some typing limitations (for example, the ID field is always optional, which is frustrating in cases when you know for sure the ID is not supposed to be null)

secondly, the link references are lazily inferred by beanie- which means type information is lost in the IDE.

its actually simpler to write our own pydantic models and return them in the repository layers, using the motor async mongodb python driver in our repository layer.

examples:

from typing import Optional
from pydantic import BaseModel, Field
from bson import ObjectId


# Custom ObjectId validator
class PyObjectId(ObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate
    
    @classmethod
    def validate(cls, v):
        if not ObjectId.is_valid(v):
            raise ValueError("Invalid ObjectId")
        return ObjectId(v)
    
    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")


# Base schema (shared logic)
class MongoModel(BaseModel):
    id: PyObjectId = Field(alias="_id")

    class Config:
        allow_population_by_field_name = True
        json_encoders = {ObjectId: str}
        arbitrary_types_allowed = True


# Create and DB variants
class UserCreate(BaseModel):
    name: str
    email: str


class UserInDB(MongoModel):
    name: str
    email: str
from motor.motor_asyncio import AsyncIOMotorClient
from pymongo import ASCENDING

client = AsyncIOMotorClient("mongodb://localhost:27017")
db = client["mydb"]
users_collection = db["users"]
from typing import List


async def create_user(user: UserCreate) -> UserInDB:
    user_dict = user.dict()
    result = await users_collection.insert_one(user_dict)
    return UserInDB(**user_dict, _id=result.inserted_id)


async def get_user_by_id(user_id: str) -> Optional[UserInDB]:
    doc = await users_collection.find_one({"_id": ObjectId(user_id)})
    return UserInDB(**doc) if doc else None


async def list_users() -> List[UserInDB]:
    cursor = users_collection.find().sort("name", ASCENDING)
    return [UserInDB(**doc) async for doc in cursor]

References:

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0