如何解决如何基于数据类设置 ORM 模型
我有一堆数据类,想将它们用作我的数据库的 ORM 模型。 为了实现我的目标,我创建了装饰器 @sa_orm,它将每个装饰的数据类映射到元数据。
问题:
- 某些字段是数据类。
- 某些字段是数据类对象的列表
OneToOne(将 child_id 列添加到父表)关系解决了第一个问题,但要解决第二个问题,我需要设置 OneToMany 关系(将 parent_id 添加到子表)。
这是简化的代码:
from dataclasses import dataclass,field,is_dataclass
from sqlalchemy import Table,MetaData,Column,Integer,String,create_engine,ForeignKey
from sqlalchemy.orm import sessionmaker,mapper,relationship
from sqlalchemy.ext.declarative import declarative_base
from typing import Optional,List
metadata = MetaData()
Base = declarative_base(metadata=metadata)
def sa_orm(metadata):
def decorator(cls):
columns = [Column('id',primary_key=True,autoincrement=True)]
children = {}
for field_name,meta in cls.__dataclass_fields__.items():
try:
field_class = meta.type.__args__[0] # If Optional or List
except AttributeError:
field_class = meta.type # If not Optional or List
if is_dataclass(field_class):
field_class_name = field_class.__name__
columns.append(Column(f"{field_class_name}_id".lower(),ForeignKey(f'{field_class_name}.id'.lower())))
children[field_name] = relationship(field_class)
else:
columns.append(Column(field_name,String))
table = Table(cls.__name__.lower(),metadata,*columns)
mapper(cls,table,properties=children)
return cls
return decorator
@sa_orm(metadata)
@dataclass
class Profession:
name: Optional[str] = field(default_factory=str)
@sa_orm(metadata)
@dataclass
class Person:
profession: Optional[Profession] = field(default=None)
name: str = field(default_factory=str)
@sa_orm(metadata)
@dataclass
class Company:
employee: List[Person] = field(default_factory=list)
name: str = field(default_factory=str)
engine = create_engine(f'postgresql://user:pass@localhost:5432',echo=True)
metadata.create_all(engine)
session = sessionmaker(bind=engine)()
developer = Profession(name="developer")
alex = Person(name="Alexander",profession=developer)
peter = Person(name="Peter")
google = Company(name="Google",employee=[alex,peter]) # OneToMany
session.add(alex) # this works - insert alex to db,insert developer to db
session.add(peter) # also works - insert peter to db
session.commit()
session.add(google) # this fails
session.close()
有没有办法将“company_id”之类的列设置为 Company 装饰器中的 person 表,或者有其他方法可以在不更改数据类的情况下链接这些表?
我有数百个这样的数据类分散在几十个文件中,也许有更好的基于数据类设置数据库的解决方案?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。