base.py
 1  """Base model for all database models."""
 2  from datetime import datetime
 3  from typing import Any, Dict, List, Optional, Type, TypeVar, Generic
 4  
 5  from sqlalchemy import Column, DateTime
 6  from sqlalchemy.ext.declarative import as_declarative, declared_attr
 7  from sqlalchemy.orm import Session
 8  
 9  ModelType = TypeVar("ModelType", bound="Base")
10  
11  @as_declarative()
12  class Base:
13      """Base model that includes common columns and methods."""
14      
15      id: Any
16      __name__: str
17      
18      # Auto-generate __tablename__ from class name
19      @declared_attr
20      def __tablename__(cls) -> str:
21          return cls.__name__.lower()
22      
23      # Timestamps
24      created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
25      updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
26      
27      def to_dict(self) -> Dict[str, Any]:
28          """Convert model instance to dictionary."""
29          return {
30              column.name: getattr(self, column.name)
31              for column in self.__table__.columns  # type: ignore
32          }
33      
34      @classmethod
35      def create(cls, db: Session, **kwargs) -> ModelType:
36          """Create a new record in the database."""
37          instance = cls(**kwargs)
38          db.add(instance)
39          db.commit()
40          db.refresh(instance)
41          return instance
42      
43      @classmethod
44      def get(cls, db: Session, id: Any) -> Optional[ModelType]:
45          """Get a record by ID."""
46          return db.query(cls).filter(cls.id == id).first()
47      
48      @classmethod
49      def get_multi(
50          cls, db: Session, *, skip: int = 0, limit: int = 100
51      ) -> List[ModelType]:
52          """Get multiple records with pagination."""
53          return db.query(cls).offset(skip).limit(limit).all()
54      
55      def update(self, db: Session, **kwargs) -> None:
56          """Update record with given values."""
57          for field, value in kwargs.items():
58              if hasattr(self, field):
59                  setattr(self, field, value)
60          db.add(self)
61          db.commit()
62          db.refresh(self)
63      
64      def delete(self, db: Session) -> None:
65          """Delete the record from the database."""
66          db.delete(self)
67          db.commit()