I want to drop all tables in database db. All I do is iterate through db.tables and
drop them one by one. However, some tables are ignored and therefore not dropped. Then I
changed drop to truncate, every table is truncated. So, what’s wrong with drop?
Here are the codes:
controllers/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()
views/admin/do_remove.html:
{{=l}}<br />{{=k}}
When I visit admin/olddo_remove, I get
['auth_user', 'auth_membership', 'auth_event', 'client', 'data']
[]
When I visit admin/do_remove, I get
['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']
If I change the drop to truncate in olddo_remove, the output will be
['auth_user', 'auth_group', 'auth_membership', 'auth_permission', 'auth_event', 'auth_cas', 'client', 'product', 'data']
[]
Why? What’s wrong?
This is going CRAZY!!
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()
Output:
['auth_group', 'auth_permission', 'auth_cas', 'product']
['auth_user', 'auth_membership', 'auth_event', 'client', 'data']
And only tables on the second line were dropped.
This is a Python issue.
db.tablesis a list object (actually, it’s a special SQLCallableList object, which inherits from list).db[table_name].drop()not only drops the table_name table from the database but also removes table_name from thedb.tableslist. So, in the for loop, you are iterating over a list and mutating that list (i.e., deleting items from it) as you iterate. This is why you’re only getting every other table. In the example that works, you are first copying the list and then iterating over the copy (which is not getting mutated in the loop), so it works as expected. Truncation works even when iterating overdb.tablesdirectly because truncation doesn’t remove the tables (from the database or fromdb.tables).Note, as mentioned above,
db.tablesis a SQLCallableList. That means thatdb.tables()returns a copy of thedb.tableslist, so you can instead iterate over the copy:The .drop() will remove the table_name from
db.tablesbut will not remove it from thedb.tables()copy over which the for loop is iterating, so everything should work as expected.