我有这个Meter对象模型
class Meter(db.Model):
"""
Model for repair meter.
"""
__tablename__ = 'meters'
id = db.Column(db.Integer, primary_key=True, nullable=False)
meter_no = db.Column(db.String(50), unique=True, nullable=False)
client = db.Column(db.String(50), unique=True, nullable=False)
problems = db.Column(db.PickleType)
functional = db.Column(db.Boolean(), default=False, server_default="false")
location = db.Column(db.Integer, db.ForeignKey('locations.id'))
date_in = db.Column(db.Date, default=dt.date.today())
date_out = db.Column(db.Date)
问题PickleType列存储包含Problem对象的ID的Python列表
然后我有这个函数试图查询米数据库表,只获得列表存储中具有特定问题id(prob_id)的Meter对象为PickleType。
def problemrate(prob_id, month):
"""
Return meters with the problem id for a particular month.
args:
prob_id (int): problem id
month (int): month number e.g. april -> 4
returns:
meters (list): list of meter objects
raises: None
"""
meters = Meter.query.filter(and_(extract('month', Meter.date_in) == month,
prob_id in Meter.problems)).all()
return meters
然而,在调用函数时我收到错误:
NotImplementedError: Operator 'getitem' is not supported on this expression
按PickleType列的内容过滤sqlalchemy查询的写入方式是什么? 有可能或sqlalchemy不支持这个吗?
答案 0 :(得分:3)
简短说明:PickleType不支持任何关系功能,例如查询/过滤器。它的目的是存储和检索。请改用sqlalchemy.orm.relationship。
详细解释:错误消息实际上是正确的。过滤器函数中的所有内容都将编译为sql查询,(打印查询以查看此内容),因此' in'运算符不会编译为有效查询,也不会编译任何其他getItem运算符。什么是工作' =='但是为此您需要传递完全相同的对象,以便它可以转换为与存储的对象相同的PickleType对象。比较是在内部完成的。
解决方案:在普通的SQL中,您可以将每个列表项分别存储在不同的表中,并通过id关联。在SQLAlchemy中,您可以执行类似的操作:
from sqlalchemy.orm import relationship
from sqlalchemy.ext.associationproxy import association_proxy
class Meter(db.Model):
"""
Model for repair meter.
"""
__tablename__ = 'meters'
id = db.Column(db.Integer, primary_key=True, nullable=False)
meter_no = db.Column(db.String(50), unique=True, nullable=False)
client = db.Column(db.String(50), unique=True, nullable=False)
meter_problems = relationship('Problem', secondary=lambda: meterproblems_table)
functional = db.Column(db.Boolean(), default=False, server_default="false")
location = db.Column(db.Integer, db.ForeignKey('locations.id'))
date_in = db.Column(db.Date, default=dt.date.today())
date_out = db.Column(db.Date)
problems = association_proxy('meter_problems', 'problem')
class Problem(db.Model):
__tablename__ = 'problem'
id = db.Column(db.Integer, primary_key=True, nullable=False)
problem = db.Column('keyword', db.String(64))
def __init__(self, problem):
self.problem = problem
meterproblems_table = db.Table(
'meterproblems',
db.metadata,
db.Column(
'meter_id',
db.Integer,
db.ForeignKey("meters.id"),
primary_key=True
),
db.Column(
'problem_id',
db.Integer,
db.ForeignKey("problem.id"),
primary_key=True
)
)
你的查询而不是:
meters = Meter.query.filter(
extract('month', Meter.date_in) == month,
Meter.meter_problems.has(keyword=prob_id)
).all()
assocation_proxy用于轻松地将项目添加到meter_problems列:
obj.problems.append('something')
obj是仪表对象。
Doumentation here