在web2py中删除所有表时,会发生一些非常奇怪的事情

时间:2012-07-28 09:59:45

标签: python database list web2py

我想删除数据库db中的所有表。我所做的就是遍历db.tables和 一个接一个地放下它们。但是,某些表会被忽略,因此不会被删除。然后我 将drop更改为truncate,每个表都被截断。那么,drop有什么问题?

以下是代码:

控制器/ admin.py:

def olddo_remove():
    response.view = 'admin/do_remove.html'
    l = []
    k = []
    for table_name in db.tables:
        l.append(table_name)
        db[table_name].drop()
        #db[table_name].truncate()
    return locals()

def do_remove():
    l = []
    k = []
    for table_name in db.tables:
        l.append(table_name)
    for table_name in l:
        k.append(table_name)
        db[table_name].drop()
    return locals()

视图/管理/ do_remove.html:

{{=l}}<br />{{=k}}

当我访问admin / olddo_remove时,我得到了

['auth_user', 'auth_membership', 'auth_event', 'client', 'data']
[] 

当我访问admin / do_remove时,我得到了

['auth_user', 'auth_group', 'auth_membership', 'auth_permission', 'auth_event', 'auth_cas', 'client', 'product', 'data']
['auth_user', 'auth_group', 'auth_membership', 'auth_permission', 'auth_event', 'auth_cas', 'client', 'product', 'data'] 

如果我将olddo_remove中的drop更改为truncate,则输出将为

['auth_user', 'auth_group', 'auth_membership', 'auth_permission', 'auth_event', 'auth_cas', 'client', 'product', 'data']
[] 

为什么呢?怎么了?

<小时/> 这是疯狂 !!

def test():
    response.view = 'admin/do_remove.html'
    l = db.tables
    k = []
    for table_name in l:
        k.append(table_name)
        db[table_name].drop()
    return locals()

输出:

['auth_group', 'auth_permission', 'auth_cas', 'product']
['auth_user', 'auth_membership', 'auth_event', 'client', 'data'] 

只有第二行的表格被删除。

1 个答案:

答案 0 :(得分:2)

这是一个Python问题。 db.tables是一个列表对象(实际上,它是一个特殊的SQLCallableList对象,它继承自列表)。 db[table_name].drop()不仅从数据库中删除table_name表,还从db.tables列表中删除table_name。因此,在for循环中,您在迭代时迭代列表并改变该列表(即,从中删除项目)。这就是为什么你只得到每一张桌子。在有效的示例中,您首先复制列表然后遍历副本(在循环中没有变异),因此它按预期工作。即使直接迭代db.tables,截断也会起作用,因为截断不会删除表(来自数据库或来自db.tables)。

注意,如上所述,db.tables是SQLCallableList。这意味着db.tables()会返回db.tables列表的副本,因此您可以在副本上进行迭代:

for table_name in db.tables():
    db[table_name].drop()

.drop()将从db.tables中删除table_name,但不会从for循环迭代的db.tables()副本中删除它,因此一切都应按预期工作。