web2py update_or_insert 增加一个计数器
web2py update_or_insert to increment a counter
我有一个 web2py 定义的数据库 table 用于计算特定用户发出请求的次数 - 所以它有整数列 'user_id' 和 'n_req'.我不想为每个可能的用户用零填充它。相反,我想检查是否存在带有 user_id 的行,如果存在,则将 'n_req' 递增 1,否则使用 'n_req' 的初始值 1 创建它。避免竞争条件,我想使用单个 update_or_insert 调用来执行此操作,例如
db.count_table.update(db.count_table.user_id == uid, user_id = uid, n_req = n_req + 1)
我想我不能这样做,但是,因为它在递增时使用了 n_req
的预先存在的值。那么我如何告诉 DAL n_req
的初始值。例如,我可以做 n_req = (n_req || 0) + 1
?
我认为在这种情况下您不能使用 .update_or_insert
方法,因为 n_rec
的值取决于是否找到记录。相反,您可以这样做:
db.define_table('count_table',
Field('user_id', 'integer', unique=True),
Field('n_rec', 'integer', default=1))
def update_count(user_id):
return db(db.count_table.user_id == user_id).update(n_rec=db.count_table.n_rec + 1)
if not update_count(uid):
try:
db.count_table.insert(user_id=uid)
except db._adapter.driver.IntegrityError:
update_count(uid)
请注意,.update
中 n_rec
的值设置为 db.count_table.n_rec + 1
,这将转换为 SQL 语句,让数据库递增现有值而不是自己明确提供最终价值。这应该避免竞争条件,以防两个请求同时更新计数。
另外,请注意 user_id
字段有一个 unique
约束。这将防止竞争条件允许为同一用户创建两个记录。在这种情况下,try/except
将捕获结果 IntegrityError
,并将对现有记录进行更新。
我有一个 web2py 定义的数据库 table 用于计算特定用户发出请求的次数 - 所以它有整数列 'user_id' 和 'n_req'.我不想为每个可能的用户用零填充它。相反,我想检查是否存在带有 user_id 的行,如果存在,则将 'n_req' 递增 1,否则使用 'n_req' 的初始值 1 创建它。避免竞争条件,我想使用单个 update_or_insert 调用来执行此操作,例如
db.count_table.update(db.count_table.user_id == uid, user_id = uid, n_req = n_req + 1)
我想我不能这样做,但是,因为它在递增时使用了 n_req
的预先存在的值。那么我如何告诉 DAL n_req
的初始值。例如,我可以做 n_req = (n_req || 0) + 1
?
我认为在这种情况下您不能使用 .update_or_insert
方法,因为 n_rec
的值取决于是否找到记录。相反,您可以这样做:
db.define_table('count_table',
Field('user_id', 'integer', unique=True),
Field('n_rec', 'integer', default=1))
def update_count(user_id):
return db(db.count_table.user_id == user_id).update(n_rec=db.count_table.n_rec + 1)
if not update_count(uid):
try:
db.count_table.insert(user_id=uid)
except db._adapter.driver.IntegrityError:
update_count(uid)
请注意,.update
中 n_rec
的值设置为 db.count_table.n_rec + 1
,这将转换为 SQL 语句,让数据库递增现有值而不是自己明确提供最终价值。这应该避免竞争条件,以防两个请求同时更新计数。
另外,请注意 user_id
字段有一个 unique
约束。这将防止竞争条件允许为同一用户创建两个记录。在这种情况下,try/except
将捕获结果 IntegrityError
,并将对现有记录进行更新。