这似乎是一个真正的初学者问题,但是我很难找到一个简单的答案。我已使用表示一对多关系的简单数据模型将其简化为基本内容:
class Room(db.Model):
__tablename__ = 'rooms'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), unique=True)
capacity = db.Column(db.Integer)
events = db.relationship('Event', backref='room')
class Event(db.Model):
__tablename__ = 'counts'
id = db.Column(db.Integer, primary_key=True)
unusedCapacity = db.Column(db.Integer)
attendance = db.Column(db.Integer)
room_id = db.Column(db.Integer, db.ForeignKey('rooms.id'))
Event.unusedCapacity
的计算方式为Room.capacity - Event.attendance
,但是我需要将值存储在列中-Room.capacity
可能会随时间而变化,但是Event.unusedCapacity
需要反映实际值事件发生时未使用的容量。
我当前正在查询会议室,然后创建活动:
room = Room.query.get(room_id) # using Flask sqlAlchemy
event = event(unusedCapacity = room.capacity - attendance, ...etc)
我的问题是:有没有一种更有效的方法来一步一步做到这一点?
答案 0 :(得分:2)
如@SuperShoot的注释中所述,对insert的查询可以计算数据库中未使用的容量,而不必先获取。如@tooTired所示的显式构造函数可以将标量子查询传递为unusedCapacity
:
class Event(db.Model):
...
def __init__(self, **kwgs):
if 'unusedCapacity' not in kwgs:
kwgs['unusedCapacity'] = \
db.select([Room.capacity - kwgs['attendance']]).\
where(Room.id == kwgs['room_id']).\
as_scalar()
super().__init__(**kwgs)
虽然可以使用client-invoked SQL expressions作为默认值,但是我不确定在不使用context-sensitive default function的情况下如何可以引用要在表达式中插入的值,但这并不完全有效出:没有内联标量子查询,SQLAlchemy尝试使用占位符传递它。
__init__
方法的缺点是,您无法使用为模型创建的表按原样执行处理未使用容量的批量插入,而必须执行相同操作的手动查询。
要注意的另一件事是,在刷新发生之前,新unusedCapacity
对象的Event
属性将保留SQL表达式对象,而不是实际值。在这方面,@ tooTired的解决方案更加透明,因为新的Event
对象将保存get go中未使用容量的数值。
答案 1 :(得分:1)
SQLAlchemy向所有模型类添加一个隐式构造函数,该构造函数为其所有列和关系接受关键字参数。您可以覆盖此内容,并传递不带未使用容量的kwarg,并在构造函数中获取房间容量:
class Event(db.Model):
# ...
#kwargs without unusedCapacity
def __init__(**kwargs):
room = Room.query.get(kwargs.get(room_id))
super(Event, self).__init__(unusedCapacity = room.capacity - kwargs.get(attendance), **kwargs)
#Create new event normally
event = Event(id = 1, attendance = 1, room_id = 1)