web2py:如何在使用 SQLFORM.smartgrid 删除之前执行指令 [英] web2py: How to execute instructions before delete using SQLFORM.smartgrid

查看:19
本文介绍了web2py:如何在使用 SQLFORM.smartgrid 删除之前执行指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 SQLFORM.smartgrid 显示表 (service_types) 中的记录列表.在智能网格的每一行都有一个删除链接/按钮来删除记录.我想在 smartgrid/web2py 实际删除记录之前执行一些代码,例如我想知道是否有引用此记录的子记录(services 表),如果有,则闪烁一条消息告诉用户该记录无法删除.这是怎么做的?

I use SQLFORM.smartgrid to show a list of records from a table (service_types). In each row of the smartgrid there is a delete link/button to delete the record. I want to executive some code before smartgrid/web2py actually deletes the record, for example I want to know if there are child records (services table) referencing this record, and if any, flash a message telling user that record cannot be deleted. How is this done?

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 对象并返回 TrueFalse> 指示记录是否可删除.如果返回False,则该记录不会显示删除"按钮,服务器上也不允许进行删除操作.

There are two options. First, the deletable argument can be a function that takes the Row object of a given record and returns True or False to indicate whether the record is deletable. If it returns False, the "Delete" button will not be shown for that record, nor the delete operation be allowed on the server.

def can_delete(row):
    return True if [some condition involving row] else False

grid = SQLFORM.smartgrid(..., deletable=can_delete)

其次,有一个 ondelete 参数,它接受 db Table 对象和记录 ID.它在删除操作之前被调用,因此为了防止删除,您可以在该函数内进行重定向:

Second, there is an ondelete argument that takes the db Table object and the record ID. It is called right before the delete operation, so to prevent the delete, you can do a redirect within that function:

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 如上所示将无法正常工作,因为重定向将无效并且表格行仍会从浏览器的网格中删除(即使数据库记录没有被删除).在这种情况下,另一种方法是向浏览器返回一个非 200 HTTP 响应,这将阻止客户端 Javascript 从表中删除行(删除仅在 Ajax 请求成功时发生).我们还应该设置 response.flash 而不是 session.flash(因为我们不会重定向/重新加载整个页面):

Note, if the grid is loaded via an Ajax component and its actions are therefore performed via Ajax, using redirect within the ondelete method as shown above will not work well, as the redirect will have no effect and the table row will still be deleted from the grid in the browser (even though the database record was not deleted). In that case, an alternative approach is to return a non-200 HTTP response to the browser, which will prevent the client-side Javascript from deleting the row from the table (the delete happens only on success of the Ajax request). We should also set response.flash instead of session.flash (because we are not redirecting/reloading the whole page):

def ondelete(table, record_id):
    record = table(record_id)
    if [some condition]:
        response.flash = 'Cannot delete this record'
        raise HTTP(403)

注意,deletableondelete 参数都可以是以表名作为键的字典,因此您可以为可能从智能网格链接的不同表指定不同的值.

Note, both the deletable and ondelete arguments can be dictionaries with table names as keys, so you can specify different values for different tables that might be linked from the smartgrid.

最后,请注意删除 URL 类似于 /appname/list_services/services/delete/services/[record ID].因此,在控制器中,您可以通过检查 request.args 中的 'delete' 是否正在请求删除.在这种情况下,request.args[-2:] 表示表名和记录 ID,您可以使用它们进行任何检查.

Finally, notice the delete URLs look like /appname/list_services/services/delete/services/[record ID]. So, in the controller, you can determine if a delete is being requested by checking if 'delete' in request.args. In that case, request.args[-2:] represents the table name and record ID, which you can use to do any checks.

这篇关于web2py:如何在使用 SQLFORM.smartgrid 删除之前执行指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆