web2py:如何在使用 SQLFORM.smartgrid 删除之前执行指令
web2py: How to execute instructions before delete using SQLFORM.smartgrid
我使用 SQLFORM.smartgrid 显示来自 table (service_types)
的记录列表。在smartgrid的每一行都有一个deletelink/button来删除记录。我想在 smartgrid/web2py 实际删除记录之前执行一些代码,例如我想知道是否有子记录 (services
table) 引用这条记录,如果有的话,闪消息告诉用户记录不能被删除。这是怎么做到的?
db.py
db.define_table('service_types',
Field('type_name', requires=[IS_NOT_EMPTY(), IS_ALPHANUMERIC()]),
format='%(type_name)s',
)
db.define_table('services',
Field('service_name',requires=[IS_NOT_EMPTY(),IS_NOT_IN_DB(db,'services.service_name')]),
Field('service_type','reference service_types',requires=IS_IN_DB(db,db.service_types.id,
'%(type_name)s',
error_message='not in table',
zero=None),
ondelete='RESTRICT',
),
Field('interest_rate','decimal(15,2)',requires=IS_DECIMAL_IN_RANGE(0,100)),
Field('max_term','integer'),
auth.signature,
format='%(service_name)s',
)
db.services._plural='Services'
db.services._singular='Service'
if db(db.service_types).count() < 1:
db.service_types.insert(type_name='Loan')
db.service_types.insert(type_name='Contribution')
db.service_types.insert(type_name='Other')
控制器
def list_services():
grid = SQLFORM.smartgrid(db.services
, fields = [db.services.service_name,db.services.service_type]
)
return locals()
查看
{{extend 'layout.html'}}
{{=grid}}
有两种选择。首先,deletable
参数可以是一个函数,它接受给定记录的 Row
对象和 returns True
或 False
来指示记录是否是删除table。如果它 returns False
,则不会为该记录显示 "Delete" 按钮,也不允许在服务器上进行删除操作。
def can_delete(row):
return True if [some condition involving row] else False
grid = SQLFORM.smartgrid(..., deletable=can_delete)
其次,有一个 ondelete
参数接受 db
Table
对象和记录 ID。它在删除操作之前被调用,所以为了防止删除,您可以在该函数内进行重定向:
def ondelete(table, record_id):
record = table(record_id)
if [some condition]:
session.flash = 'Cannot delete this record'
redirect(URL())
grid = SQLFORM.smartgrid(..., ondelete=ondelete)
请注意,如果网格是通过 Ajax 组件加载的,因此其操作是通过 Ajax 执行的,请在 ondelete
方法中使用 redirect
,如上所示不会很好地工作,因为重定向没有效果并且 table 行仍然会从浏览器的网格中删除(即使数据库记录没有被删除)。在这种情况下,另一种方法是 return 向浏览器发送非 200 HTTP 响应,这将阻止客户端 Javascript 从 table 中删除行(删除仅在 Ajax 请求成功时发生)。我们还应该设置 response.flash
而不是 session.flash
(因为我们不是 redirecting/reloading 整个页面):
def ondelete(table, record_id):
record = table(record_id)
if [some condition]:
response.flash = 'Cannot delete this record'
raise HTTP(403)
请注意,deletable
和 ondelete
参数都可以是以 table 名称作为键的字典,因此您可以为不同的 table 指定不同的值,这可能从智能电网链接。
最后,请注意删除 URL 看起来像 /appname/list_services/services/delete/services/[record ID]
。因此,在控制器中,您可以通过检查 'delete' in request.args
来确定是否正在请求删除。在这种情况下,request.args[-2:]
代表 table 名称和记录 ID,您可以使用它们进行任何检查。
根据 Anthony 的回答,我选择了第二个选项并得出以下结论:
def ondelete_service_type(service_type_table, service_type_id):
count = db(db.services.service_type == service_type_id).count()
if count > 0:
session.flash = T("Cant delete")
#redirect(URL('default','list_service_types#'))
else:
pass
return locals()
def list_service_types():
grid = SQLFORM.smartgrid(db.service_types
, fields = [db.service_types.type_name, db.services.service_name]
, ondelete = ondelete_service_type
)
return locals()
但是,如果我这样做...
if count > 0:
session.flash = T("Cant delete")
else:
pass
return locals()
我收到这个错误:
如果我这样做:
if count > 0:
session.flash = T("Cant delete")
redirect(URL('default','list_service_types#')) <== please take note
else:
pass
return locals()
我收到 flash 错误消息 Cant delete
但记录似乎已从列表中删除,并在使用 F5 刷新页面后重新出现(显然是因为数据库中不允许删除,这是有意的)。
我应该修复哪一个以及如何修复?
备注
如果这些问题中的任何一个得到解决,我可以接受安东尼的回答。
我使用 SQLFORM.smartgrid 显示来自 table (service_types)
的记录列表。在smartgrid的每一行都有一个deletelink/button来删除记录。我想在 smartgrid/web2py 实际删除记录之前执行一些代码,例如我想知道是否有子记录 (services
table) 引用这条记录,如果有的话,闪消息告诉用户记录不能被删除。这是怎么做到的?
db.py
db.define_table('service_types',
Field('type_name', requires=[IS_NOT_EMPTY(), IS_ALPHANUMERIC()]),
format='%(type_name)s',
)
db.define_table('services',
Field('service_name',requires=[IS_NOT_EMPTY(),IS_NOT_IN_DB(db,'services.service_name')]),
Field('service_type','reference service_types',requires=IS_IN_DB(db,db.service_types.id,
'%(type_name)s',
error_message='not in table',
zero=None),
ondelete='RESTRICT',
),
Field('interest_rate','decimal(15,2)',requires=IS_DECIMAL_IN_RANGE(0,100)),
Field('max_term','integer'),
auth.signature,
format='%(service_name)s',
)
db.services._plural='Services'
db.services._singular='Service'
if db(db.service_types).count() < 1:
db.service_types.insert(type_name='Loan')
db.service_types.insert(type_name='Contribution')
db.service_types.insert(type_name='Other')
控制器
def list_services():
grid = SQLFORM.smartgrid(db.services
, fields = [db.services.service_name,db.services.service_type]
)
return locals()
查看
{{extend 'layout.html'}}
{{=grid}}
有两种选择。首先,deletable
参数可以是一个函数,它接受给定记录的 Row
对象和 returns True
或 False
来指示记录是否是删除table。如果它 returns False
,则不会为该记录显示 "Delete" 按钮,也不允许在服务器上进行删除操作。
def can_delete(row):
return True if [some condition involving row] else False
grid = SQLFORM.smartgrid(..., deletable=can_delete)
其次,有一个 ondelete
参数接受 db
Table
对象和记录 ID。它在删除操作之前被调用,所以为了防止删除,您可以在该函数内进行重定向:
def ondelete(table, record_id):
record = table(record_id)
if [some condition]:
session.flash = 'Cannot delete this record'
redirect(URL())
grid = SQLFORM.smartgrid(..., ondelete=ondelete)
请注意,如果网格是通过 Ajax 组件加载的,因此其操作是通过 Ajax 执行的,请在 ondelete
方法中使用 redirect
,如上所示不会很好地工作,因为重定向没有效果并且 table 行仍然会从浏览器的网格中删除(即使数据库记录没有被删除)。在这种情况下,另一种方法是 return 向浏览器发送非 200 HTTP 响应,这将阻止客户端 Javascript 从 table 中删除行(删除仅在 Ajax 请求成功时发生)。我们还应该设置 response.flash
而不是 session.flash
(因为我们不是 redirecting/reloading 整个页面):
def ondelete(table, record_id):
record = table(record_id)
if [some condition]:
response.flash = 'Cannot delete this record'
raise HTTP(403)
请注意,deletable
和 ondelete
参数都可以是以 table 名称作为键的字典,因此您可以为不同的 table 指定不同的值,这可能从智能电网链接。
最后,请注意删除 URL 看起来像 /appname/list_services/services/delete/services/[record ID]
。因此,在控制器中,您可以通过检查 'delete' in request.args
来确定是否正在请求删除。在这种情况下,request.args[-2:]
代表 table 名称和记录 ID,您可以使用它们进行任何检查。
根据 Anthony 的回答,我选择了第二个选项并得出以下结论:
def ondelete_service_type(service_type_table, service_type_id):
count = db(db.services.service_type == service_type_id).count()
if count > 0:
session.flash = T("Cant delete")
#redirect(URL('default','list_service_types#'))
else:
pass
return locals()
def list_service_types():
grid = SQLFORM.smartgrid(db.service_types
, fields = [db.service_types.type_name, db.services.service_name]
, ondelete = ondelete_service_type
)
return locals()
但是,如果我这样做...
if count > 0:
session.flash = T("Cant delete")
else:
pass
return locals()
我收到这个错误:
如果我这样做:
if count > 0:
session.flash = T("Cant delete")
redirect(URL('default','list_service_types#')) <== please take note
else:
pass
return locals()
我收到 flash 错误消息 Cant delete
但记录似乎已从列表中删除,并在使用 F5 刷新页面后重新出现(显然是因为数据库中不允许删除,这是有意的)。
我应该修复哪一个以及如何修复?
备注 如果这些问题中的任何一个得到解决,我可以接受安东尼的回答。