我正在尝试使用SQLAlchemy的@aggregated装饰器为Receipt类定义一个属性('gross_amount)‘。此gross_amount属性是通过外部id与Item实例关联的所有Receipt实例的Item.gross_amount总和。
也就是说,收据是由项目组成的,我想定义一个收据'gross_amount‘值,它就是收据上所有项目的总和$。
我根据这个文档http://sqlalchemy-utils.readthedocs.io/en/latest/aggregates.html对代码进行了建模
所以看起来像这样..。
from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.sql import func
from sqlalchemy import orm
class Receipt(Base):
__tablename__ = "receipts"
__table_args__ = {'extend_existing': True}
id = Column(Integer, index = True, primary_key = True, nullable = False)
@aggregated('itemz', Column(Integer))
def gross_amount(self):
return func.sum(Item.gross_amount)
itemz = orm.relationship(
'Item',
backref='receipts'
)
class Item(Base):
__tablename__ = "items"
id = Column(Integer, index = True, primary_key = True, nullable = False)
'''
FE relevant
'''
gross_amount = Column(Integer)
receipt_id = Column(Integer, ForeignKey("receipts.id"), nullable=False)在我的迁移中,是否应该在receipts表中为gross_amount设置一个列? 1)当我在receipts表中定义该列时,任何实例的任何Receipt.gross_amount都只指向在receipts表中定义的gross_amount值。2)当我没有在receipts表中定义这一列时,每当我对数据库执行一个SQLAlchemy时,我就会得到一个SELECT错误:
ProgrammingError: (psycopg2.ProgrammingError) column receipts.gross_amount does not exist
仅供参考,我的SQLAlchemy包是通过PIP分发的最新版本。
SQLAlchemy==1.1.11
SQLAlchemy-Utils==0.32.14我现在运行的本地数据库是PostgreSQL 9.6.2
我在这里做错了什么?任何病人的帮助都将不胜感激!
发布于 2018-01-27 00:53:02
是的,您确实需要将列添加到表中:
CREATE TABLE receipts (
id INTEGER NOT NULL,
gross_amount INTEGER, -- <<< See, it's here :)
PRIMARY KEY (id)
);
INSERT INTO receipts VALUES(1,7);
INSERT INTO receipts VALUES(2,7);
CREATE TABLE items (
id INTEGER NOT NULL,
gross_amount INTEGER,
receipt_id INTEGER NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(receipt_id) REFERENCES receipts (id)
);使用此自包含的代码片段进行测试:
from sqlalchemy import Column, Integer, ForeignKey, create_engine, orm
from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql import func
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy_utils import aggregated
Base = declarative_base()
class Receipt(Base):
__tablename__ = "receipts"
__table_args__ = {'extend_existing': True}
id = Column(Integer, index = True, primary_key = True, nullable = False)
@aggregated('itemz', Column(Integer))
def gross_amount(self):
return func.sum(Item.gross_amount)
itemz = orm.relationship('Item', backref='receipts')
class Item(Base):
__tablename__ = "items"
id = Column(Integer, index = True, primary_key = True, nullable = False)
gross_amount = Column(Integer)
receipt_id = Column(Integer, ForeignKey("receipts.id"), nullable=False)
def __init__(self, amount):
self.gross_amount=amount
engine = create_engine('sqlite:///xxx.db', echo=True)
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)()
receipt = Receipt()
receipt.itemz.append(Item(5))
receipt.itemz.append(Item(2))
session.add(receipt)
session.commit()
print (receipt.gross_amount)当然,还有另一种称为hybrid_property的方法,它基本上允许您同时执行orm级和数据库级查询,而无需在数据库中添加额外的列:
@hybrid_property
def gross_sum(self):
return sum(i.gross_amount for i in self.itemz)
@gross_sum.expression
def gross_sum(cls):
return select([func.sum(Item.gross_amount)]).\
where(Item.receipt_id==cls.id).\
label('gross_sum')发布于 2018-01-26 20:26:29
出现此错误的原因是您添加的新列(gross_amount)尚未在数据库的receipts表中创建。
这意味着,您当前的数据库表只有一个已创建的列(id)。要使聚合列正常工作,它需要包含一个名为gross_amount的附加列。
此附加列必须允许null值。
其中一种方法是直接在PostgreSQL中使用SQL:
ALTER TABLE receipts ADD gross_amount int;或者,如果还没有数据,可以通过SQLAlchemy删除并重新创建表。它应该会自动创建这个额外的列。
我不知道你说的最后一部分是什么意思:
当我在receipts表中定义此列时,任何实例的任何Receipt.gross_amount都只是指向receipts表中定义的gross_amount值。
这就是它应该指向的地方。我不知道你这么说是什么意思。您的意思是,即使此收据的项目在Item中有值,它也不包含任何值?如果是这样的话,我会仔细检查是否是这种情况(并且根据their examples here,在看到结果之前刷新数据库会话)。
https://stackoverflow.com/questions/45024854
复制相似问题