python - 如何在普通类中使用相当于 __post_init__ 方法的方法?

标签 python sqlalchemy

我想存储代码中使用的实体并避免多次出现。因此,我的想法是使用 __init__ 方法来收集我的类的主要数据,然后使用一种 __post_init__ 方法从我的类对象中计算 id。这是代码:

class Worker(Base):
    __tablename__='worker'
    id = Column(Integer,primary_key=True)
    profile=Column(String(100),nullable=False)
    useragent=Column(String(100),nullable=False)
    def __init__(self,useragent,profile):
        """ specify the main information"""
        print('init')
        self.profile= profile
        self.useragent=useragent
    def __post_init__(self):
        """ compute an id based on self, the worker"""
        self.id=id(self)
        print('dans post init')

在这个示例中,可以使用 __init__ 方法,但它不会像我们期望的数据类那样运行 __post_init__ 方法。

如何在执行 __init__ 方法后立即运行此方法?

最佳答案

__post_init__方法特定于dataclasses图书馆,因为 __init__方法dataclass生成类并覆盖它会完全违背生成它的目的。

另一方面,SQLAlchemy 提供 __init__基本模型类的实现(使用 declarative_base() 为您生成)。设置默认值后,您可以通过super().__init__()安全地重新使用该方法。 。考虑到 SQLAlchemy -提供__init__方法仅接受关键字参数:

def __init__(self, useragent, profile):
    """specify the main information"""
    id = generate_new_id(self)
    super().__init__(id=id, useragent=useragent, profile=profile)

如果您需要等待其他列首先获得更新值(因为它们可能将 Python 函数定义为 default ),那么您也可以在调用 super().__init__() 之后运行函数,然后分配给 self :

def __init__(self, useragent, profile):
    """specify the main information"""
    super().__init__(useragent=useragent, profile=profile)
    self.id = generate_new_id(self)

注意:您不想使用内置 id() function要为 SQL 插入的数据生成 id,函数返回的值不保证是唯一的。它们仅对于所有事件 Python 对象的集合是唯一的,并且仅在当前进程中是唯一的。下次运行 Python 时,或者从内存中删除对象时,值可以并且将会被重用,并且您无法控制下次或完全在不同的进程中生成哪些值。

如果您只想创建具有 useragent 的独特组合的行和profile列,那么你需要定义一个 UniqueConstraint table arguments 。不要尝试在 Python 级别检测唯一性,因为您无法保证另一个进程不会同时进行相同的检查。数据库可以更好地确定是否有重复值,而无需冒竞争条件的风险:

class Worker(Base):
    __tablename__='worker'
    id = Column(Integer, primary_key=True, autoincrement=True)
    profile = Column(String(100), nullable=False)
    useragent = Column(String(100), nullable=False)

    __table_args__ = (
        UniqueConstraint("profile", "useragent"),
    )

或者您可以使用基于两列的复合主键;主键(复合或其他)必须始终是唯一的:

class Worker(Base):
    __tablename__='worker'
    profile = Column(String(100), primary_key=True, nullable=False)
    useragent = Column(String(100), primary_key=True, nullable=False)

关于python - 如何在普通类中使用相当于 __post_init__ 方法的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55183333/

相关文章:

python - SQLAlchemy 属性错误 : 'NoneType' object has no attribute '_getter'

python - Mongoengine更新嵌入文档

python - SqlAlchemy 超前缓存?

python - SQLAlchemy ORM 插入相关对象而不选择它们

python - 从子图元素中获取已打印标签的列表,以避免图例中的重复输入

python - 使用 SqlAlchemy 和 Id 为 PostgreSQL 创建夹具数据

python - 如何获得flask_sqlalchemy 类的PEP 484 类型提示?

python - 将 ValidationError 提升为字典时出错

python - 如何根据 Pandas 中第一个数据帧中的某些列值添加第二个数据帧中的列值

python - Django 中一个请求中的 GraphQL 多个查询