能否通过classmethod引用类内多个变量?合并SQL CRUD与模型类
可以通过classmethod合并模型类与CRUD逻辑
当然可以用classmethod(或直接在类内定义方法)来引用类中定义的字段,把SQL模型类和CRUD操作合并到同一个类里是完全可行的,能有效简化代码结构。下面结合ORM(比如SQLAlchemy)和原生SQL两种场景给出实现方案:
基于SQLAlchemy的实现(最常用场景)
如果用SQLAlchemy这类ORM,直接把CRUD方法作为classmethod写在模型类里即可,类中定义的字段会自动映射到数据库表,在方法里通过cls就能引用这些字段:
from __future__ import annotations from sqlalchemy import Column, String, Integer from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import Session Base = declarative_base() class Person(Base): __tablename__ = "persons" # 指定对应数据库表名 # 定义数据库字段,同时保留类型注解 id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True) gender = Column(String) age = Column(Integer) @classmethod def get_all(cls, db: Session) -> list[Person]: # 直接查询当前类对应的表,返回所有Person实例 return db.query(cls).all() @classmethod def create(cls, db: Session, name: str, gender: str, age: int) -> Person: # 实例化当前类,传入字段值 new_person = cls(name=name, gender=gender, age=age) db.add(new_person) db.commit() db.refresh(new_person) return new_person @classmethod def get_by_name(cls, db: Session, name: str) -> Person | None: # 通过类字段过滤查询,cls.name对应数据库表的name列 return db.query(cls).filter(cls.name == name).first()
关键说明
- 类中定义的
name、gender等字段,在classmethod里通过cls.name就能直接引用,ORM会自动关联到数据库表的对应列。 db.query(cls)等价于原来分开实现时的db.query(ModelPerson),因为cls就是当前的模型类本身。- 所有CRUD逻辑都封装在同一个类中,代码更集中,避免跨类引用的繁琐。
原生SQL场景(手动处理SQL语句)
如果不用ORM,需要手动拼接SQL,也可以通过类的__annotations__属性获取所有定义的字段:
from __future__ import annotations import sqlite3 class Person: name: str gender: str age: int @classmethod def get_field_names(cls) -> list[str]: # 获取类中定义的所有字段名 return list(cls.__annotations__.keys()) @classmethod def create(cls, db_conn: sqlite3.Connection, **kwargs) -> None: fields = cls.get_field_names() # 拼接INSERT语句 insert_sql = f"INSERT INTO persons ({', '.join(fields)}) VALUES ({', '.join(['?' for _ in fields])})" db_conn.execute(insert_sql, tuple(kwargs[field] for field in fields)) db_conn.commit()
关键说明
cls.__annotations__会返回类中所有类型注解的字段(比如{'name': str, 'gender': str, 'age': int}),通过它可以动态获取字段列表,不用手动重复写字段名。- 适合需要完全自定义SQL逻辑的场景,同样能实现模型与CRUD的合并。
内容的提问来源于stack exchange,提问作者sokeefe
相关产品推荐
相关产品推荐

