gpt4 book ai didi

python - SQLAlchemy mixin,如何从它们继承和变量关系

转载 作者:行者123 更新时间:2023-12-05 04:48:57 26 4
gpt4 key购买 nike

我已经开始使用 SQLAlchemy Mixins 并且我已经阅读了文档。它很有用,但我仍然发现我对我希望完成的事情有疑问。我应该说我对 SQLAlchemy 不是很有经验。

所以我想要的是一种将列和关系从 Mixin 继承到子类的方法。目前我有前者在工作,但没有后者。

文档中对这些关系的解释如下:

@declarative_mixin
class RefTargetMixin:
@declared_attr
def target_id(cls):
return Column('target_id', ForeignKey('target.id'))

@declared_attr
def target(cls):
return relationship("Target")

这似乎正是我在功能方面寻找的东西,除了一点:除非我弄错了,'target' 作为一个字符串在这里是固定的并且不是可变的。如果我要提出一个通用版本,我希望能够让一个子类指定与其有关系的表名和类。

不幸的是,这就是我卡住的地方。我只是不知道该怎么做。我做了一些相当原始的尝试,例如:

@declared_attr
def target_id(cls, targetTable):
return Column('target_id', ForeignKey(f'{targetTable}.id'))

但是我不知道如何“调用”这个方法。我尝试从子类 init 调用“super”,但它一直告诉我:

TypeError: target_id() missing 1 required positional argument: 'targetTable'

我认为这行不通,但我只是不确定正确的方法是什么,我想我至少会尝试一下,然后再问这里。

最佳答案

我确实找到了答案,我想我会回来展示我是如何做到的。

经过一番搜索,我找到了this question这成为解决方案的基础。这并不准确,但它表明如果您知道如何去做,这些@declared_attr 的东西可以是可变的。

因此,让我们从 target_id 属性开始,这是我在这里拥有的。还有更多,我会谈到,但我会从那开始。顺便说一下,这一切都在“父”mixin 中。

基本模式是您需要一个 setter、一个 getter 和一个变量本身,如下所示:

_targetTableName = 'Not defined target table name'

def get_targetTableName(self):
return self._targetTableName

def set_targetTableName(self, value):
self._targetTableName = value

@declared_attr
def targetTableName(cls):
return synonym('_targetTableName', descriptor=property(cls.get_targetTableName, cls.set_targetTableName))

然后我在同一个 mixin 中也需要这个:

@declared_attr
def target_id(cls):
return Column('target_id', ForeignKey(f'{cls.targetTableName}.ID'))

如您所见,这允许我更改 ForeignKey 参数中的内容 - 毕竟它只是一个字符串。

作为一个相对新手,我要问的下一个问题是如何更改子项中的“targetTableName”属性?嗯,就像这样:

class TestChild(TestParent, med.DeclarativeBase):
__tablename__='testChild01'
targetTableName = 'SchoolTypes'

现在,当它全部自动创建时,您的子类将有一个外键,在本例中为 SchoolTypes.ID。

但是等等,如果目标中的列不叫“ID”怎么办?那么你也可以用同样的方式使它成为一个变量。我选择不这样做,因为我所有的表都有一个“ID”列(我不知道这是好事还是坏事)。

但是等等,还有更多!

你看,实际上 target_id 只是等式的一部分,我希望,如果我能解决这个问题,我就能得到奖品的另一部分:链接的对象。也就是说,SQLAlchemy“关系”类型为您提供由外键链接的对象。

正常创建时,它看起来像这样:

targetType = relationship('SchoolType', foreign_keys='Search_Grade_SchoolType.targetID')

那么如何使它也具有通用性呢?好吧,使用与上述相同的过程来使设置的事物可变。

我把代码整体分享给大家,让大家更容易看懂。但请注意,我所做的只是为目标表名、目标类名和当前类名设置一个变量,所有这些都是您需要的:

from sqlalchemy import Column, Integer, Boolean, String, DateTime, ForeignKey
from sqlalchemy.orm import backref, relationship

from sqlalchemy.orm import declarative_mixin, synonym
from sqlalchemy.orm import declared_attr

@declarative_mixin
class TestParent:
id = Column('ID', Integer, primary_key=True, autoincrement=True)

_targetTableName = 'Not defined target table name'
_targetClassName = 'Not defined target class name'
_myClassName = 'Not defined class name'

def get_myClassName(self):
return self._myClassName

def set_myClassName(self, value):
self._myClassName = value

@declared_attr
def myClassName(cls):
return synonym('_myClassName', descriptor=property(cls.get_myClassName, cls.set_myClassName))

def get_targetTableName(self):
return self._targetTableName

def set_targetTableName(self, value):
self._targetTableName = value

@declared_attr
def targetTableName(cls):
return synonym('_targetTableName', descriptor=property(cls.get_targetTableName, cls.set_targetTableName))

def get_targetClassName(self):
return self._targetClassName

def set_targetClassName(self, value):
self._targetClassName = value

@declared_attr
def target_id(cls):
return Column('target_id', ForeignKey(f'{cls.targetTableName}.ID'))

@declared_attr
def targetClassName(cls):
return synonym('_targetClassName', descriptor=property(cls.get_targetClassName, cls.set_targetClassName))

@declared_attr
def target_object(cls):
return relationship(f'{cls.targetClassName}', foreign_keys=f'{cls.myClassName}.target_id')


class TestChild(TestParent, med.DeclarativeBase):
__tablename__='testChild01'
name = Column('NAME', String(50), unique=False)
targetTableName = 'SchoolTypes'
targetClassName = 'SchoolType'
myClassName = 'TestChild'

def __init__(self, name, targetID):
self.name = name
self.target_id = targetID

def TestMethod(self):
print(f'Print me!')

那么这一切有什么用呢?它允许子类 (TestChild) 通过在子类中输入几个变量来设置 target_object 和 target_id 等。父项可以有任意多的列,子项也可以有,但它们也可以有自己的列(在这种情况下,父项的“ID”,子项的“姓名”。

我为什么要做这一切?它解决了什么?好吧,我知道我会有很多实际上是同一件事的 table 。相同的结构,除了它们有指向彼此不同表的外键。所以我想要某种继承情况以允许重用代码,也允许我偷懒。

关于python - SQLAlchemy mixin,如何从它们继承和变量关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67738904/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com