71
76
return shortcuts.redirect('http://example.com/%s' % len(object_ids))
79
class MyUpdateAction(tables.UpdateAction):
80
def get_data(self, request, obj_id):
84
class MyBatchAction(tables.BatchAction):
86
action_present = _("Batch")
87
action_past = _("Batched")
88
data_type_singular = _("Item")
89
data_type_plural = _("Items")
91
def action(self, request, object_ids):
95
class MyToggleAction(tables.BatchAction):
97
action_present = (_("Down"), _("Up"))
98
action_past = (_("Downed"), _("Upped"))
99
data_type_singular = _("Item")
100
data_type_plural = _("Items")
102
def allowed(self, request, obj=None):
105
self.down = getattr(obj, 'status', None) == 'down'
107
self.current_present_action = 1
108
return self.down or getattr(obj, 'status', None) == 'up'
110
def action(self, request, object_ids):
113
self.current_past_action = 1
74
116
class MyFilterAction(tables.FilterAction):
75
117
def filter(self, table, objs, filter_string):
76
118
q = filter_string.lower()
107
149
verbose_name = "My Table"
108
150
status_column = "status"
109
151
columns = ('id', 'name', 'value', 'optional', 'status')
110
table_actions = (MyFilterAction, MyAction,)
111
row_actions = (MyAction, MyLinkAction,)
152
table_actions = (MyFilterAction, MyAction, MyBatchAction)
153
row_actions = (MyAction, MyLinkAction, MyUpdateAction,
154
MyBatchAction, MyToggleAction)
114
157
class DataTableTests(test.TestCase):
136
179
'<Column: actions>'])
137
180
# Actions (these also test ordering)
138
181
self.assertQuerysetEqual(self.table.base_actions.values(),
139
['<MyAction: click>',
182
['<MyBatchAction: batch>',
183
'<MyAction: delete>',
140
184
'<MyFilterAction: filter>',
141
'<MyLinkAction: login>'])
185
'<MyLinkAction: login>',
186
'<MyToggleAction: toggle>',
187
'<MyUpdateAction: update>'])
142
188
self.assertQuerysetEqual(self.table.get_table_actions(),
143
189
['<MyFilterAction: filter>',
144
'<MyAction: click>'])
190
'<MyAction: delete>',
191
'<MyBatchAction: batch>'])
145
192
self.assertQuerysetEqual(self.table.get_row_actions(TEST_DATA[0]),
146
['<MyAction: click>',
147
'<MyLinkAction: login>'])
193
['<MyAction: delete>',
194
'<MyLinkAction: login>',
195
'<MyUpdateAction: update>',
196
'<MyBatchAction: batch>',
197
'<MyToggleAction: toggle>'])
148
198
# Auto-generated columns
149
199
multi_select = self.table.columns['multi_select']
150
200
self.assertEqual(multi_select.auto, "multi_select")
318
368
resp = http.HttpResponse(table_actions)
319
369
self.assertContains(resp, "table_search", 1)
320
370
self.assertContains(resp, "my_table__filter__q", 1)
321
self.assertContains(resp, "my_table__click", 1)
371
self.assertContains(resp, "my_table__delete", 1)
323
373
row_actions = self.table.render_row_actions(TEST_DATA[0])
324
374
resp = http.HttpResponse(row_actions)
325
self.assertContains(resp, "<li", 1)
326
self.assertContains(resp, "my_table__click__1", 1)
375
self.assertContains(resp, "<li", 4)
376
self.assertContains(resp, "my_table__delete__1", 1)
377
self.assertContains(resp,
378
"action=update&table=my_table&obj_id=1", 1)
379
self.assertContains(resp, "data-update-interval", 1)
380
self.assertContains(resp, "my_table__toggle__1", 1)
327
381
self.assertContains(resp, "/auth/login/", 1)
328
382
self.assertContains(resp, "ajax-modal", 1)
345
399
def test_table_actions(self):
346
400
# Single object action
347
action_string = "my_table__click__1"
401
action_string = "my_table__delete__1"
348
402
req = self.factory.post('/my_url/', {'action': action_string})
349
403
self.table = MyTable(req, TEST_DATA)
350
404
self.assertEqual(self.table.parse_action(action_string),
351
('my_table', 'click', '1'))
405
('my_table', 'delete', '1'))
352
406
handled = self.table.maybe_handle()
353
407
self.assertEqual(handled.status_code, 302)
354
408
self.assertEqual(handled["location"], "http://example.com/1")
410
# Batch action (without toggle) conjugation behavior
411
req = self.factory.get('/my_url/')
412
self.table = MyTable(req, TEST_DATA_3)
413
toggle_action = self.table.get_row_actions(TEST_DATA_3[0])[3]
414
self.assertEqual(unicode(toggle_action.verbose_name), "Batch Item")
416
# Single object toggle action
417
# GET page - 'up' to 'down'
418
req = self.factory.get('/my_url/')
419
self.table = MyTable(req, TEST_DATA_3)
420
self.assertEqual(len(self.table.get_row_actions(TEST_DATA_3[0])), 5)
421
toggle_action = self.table.get_row_actions(TEST_DATA_3[0])[4]
422
self.assertEqual(unicode(toggle_action.verbose_name), "Down Item")
424
# Toggle from status 'up' to 'down'
426
action_string = "my_table__toggle__1"
427
req = self.factory.post('/my_url/', {'action': action_string})
428
self.table = MyTable(req, TEST_DATA)
429
self.assertEqual(self.table.parse_action(action_string),
430
('my_table', 'toggle', '1'))
431
handled = self.table.maybe_handle()
432
self.assertEqual(handled.status_code, 302)
433
self.assertEqual(handled["location"], "/my_url/")
434
self.assertEqual(list(req._messages)[0].message,
435
u"Downed Item: object_1")
437
# Toggle from status 'down' to 'up'
438
# GET page - 'down' to 'up'
439
req = self.factory.get('/my_url/')
440
self.table = MyTable(req, TEST_DATA_2)
441
self.assertEqual(len(self.table.get_row_actions(TEST_DATA_2[0])), 4)
442
toggle_action = self.table.get_row_actions(TEST_DATA_2[0])[3]
443
self.assertEqual(unicode(toggle_action.verbose_name), "Up Item")
446
action_string = "my_table__toggle__2"
447
req = self.factory.post('/my_url/', {'action': action_string})
448
self.table = MyTable(req, TEST_DATA)
449
self.assertEqual(self.table.parse_action(action_string),
450
('my_table', 'toggle', '2'))
451
handled = self.table.maybe_handle()
452
self.assertEqual(handled.status_code, 302)
453
self.assertEqual(handled["location"], "/my_url/")
454
self.assertEqual(list(req._messages)[0].message,
455
u"Upped Item: object_2")
356
457
# Multiple object action
357
action_string = "my_table__click"
458
action_string = "my_table__delete"
358
459
req = self.factory.post('/my_url/', {'action': action_string,
359
460
'object_ids': [1, 2]})
360
461
self.table = MyTable(req, TEST_DATA)
361
462
self.assertEqual(self.table.parse_action(action_string),
362
('my_table', 'click', None))
463
('my_table', 'delete', None))
363
464
handled = self.table.maybe_handle()
364
465
self.assertEqual(handled.status_code, 302)
365
466
self.assertEqual(handled["location"], "http://example.com/2")
382
483
self.assertEqual(handled, None)
383
484
self.assertQuerysetEqual(self.table.filtered_data,
384
485
['<FakeObject: object_2>'])
487
# Updating and preemptive actions
488
params = {"table": "my_table", "action": "update", "obj_id": "1"}
489
req = self.factory.get('/my_url/',
491
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
492
self.table = MyTable(req)
493
resp = self.table.maybe_preempt()
494
self.assertEqual(resp.status_code, 200)
495
# Make sure the data returned differs from the original
496
self.assertContains(resp, "my_table__row__1")
497
self.assertContains(resp, "status_down")
499
# Verify that we don't get a response for a valid action with the
501
params = {"table": "my_table", "action": "delete", "obj_id": "1"}
502
req = self.factory.get('/my_url/', params)
503
self.table = MyTable(req)
504
resp = self.table.maybe_preempt()
505
self.assertEqual(resp, None)
506
resp = self.table.maybe_handle()
507
self.assertEqual(resp, None)
510
table_actions = self.table.get_table_actions()
511
self.assertEqual(unicode(table_actions[0].verbose_name), "filter")
512
self.assertEqual(unicode(table_actions[1].verbose_name), "Delete Me")
514
row_actions = self.table.get_row_actions(TEST_DATA[0])
515
self.assertEqual(unicode(row_actions[0].verbose_name), "Delete Me")
516
self.assertEqual(unicode(row_actions[1].verbose_name), "Log In")