Ensure DataTableView applies filter after redirect
Non-API bound filters were not persisting across pages changes, this patch adds an additional check to make sure the DataTable looks for any non api bound filters in the session and applies them on page load. Also added some logic to make Project filter in Admin->Instances API bound using the tenant_id. Change-Id: Ieab9f2b92b59401809725a4f37628757dc4c8f13 Closes-Bug: 1369014
This commit is contained in:
parent
05d0f07317
commit
9ca494e6e3
|
@ -1178,17 +1178,20 @@ class DataTable(object):
|
|||
if self._meta.filter and self._meta._filter_action:
|
||||
action = self._meta._filter_action
|
||||
filter_string = self.get_filter_string()
|
||||
filter_field = self.get_filter_field()
|
||||
request_method = self.request.method
|
||||
needs_preloading = (not filter_string
|
||||
and request_method == 'GET'
|
||||
and action.needs_preloading)
|
||||
valid_method = (request_method == action.method)
|
||||
if valid_method or needs_preloading:
|
||||
filter_field = self.get_filter_field()
|
||||
not_api_filter = (filter_string
|
||||
and not action.is_api_filter(filter_field))
|
||||
|
||||
if valid_method or needs_preloading or not_api_filter:
|
||||
if self._meta.mixed_data_type:
|
||||
self._filtered_data = action.data_type_filter(
|
||||
self, self.data, filter_string)
|
||||
elif not action.is_api_filter(filter_field):
|
||||
else:
|
||||
self._filtered_data = action.filter(
|
||||
self, self.data, filter_string)
|
||||
return self._filtered_data
|
||||
|
|
|
@ -226,11 +226,10 @@ class DataTableView(MultiTableView):
|
|||
return None
|
||||
param_name = filter_action.get_param_name()
|
||||
filter_string = request.POST.get(param_name)
|
||||
filter_string_session = request.session.get(param_name)
|
||||
changed = (filter_string is not None and
|
||||
filter_string_session is not None and
|
||||
filter_string != filter_string_session)
|
||||
if filter_string is None and filter_string_session is not None:
|
||||
filter_string_session = request.session.get(param_name, "")
|
||||
changed = (filter_string is not None
|
||||
and filter_string != filter_string_session)
|
||||
if filter_string is None:
|
||||
filter_string = filter_string_session
|
||||
filter_field_param = param_name + '_field'
|
||||
filter_field = request.POST.get(filter_field_param)
|
||||
|
|
|
@ -1343,25 +1343,65 @@ class DataTableViewTests(test.TestCase):
|
|||
self.assertEqual(TableWithPermissions,
|
||||
context['table_with_permissions_table'].__class__)
|
||||
|
||||
def test_api_filter_table_view(self):
|
||||
filter_value_param = "my_table__filter__q"
|
||||
filter_field_param = '%s_field' % filter_value_param
|
||||
req = self.factory.post('/my_url/', {filter_value_param: 'up',
|
||||
filter_field_param: 'status'})
|
||||
req.user = self.user
|
||||
fil_value_param = "my_table__filter__q"
|
||||
fil_field_param = '%s_field' % fil_value_param
|
||||
|
||||
def _test_filter_setup_view(self, request):
|
||||
view = APIFilterTableView()
|
||||
view.request = req
|
||||
view.request = request
|
||||
view.kwargs = {}
|
||||
view.handle_server_filter(req)
|
||||
view.handle_server_filter(request)
|
||||
return view
|
||||
|
||||
def test_api_filter_table_view(self):
|
||||
req = self.factory.post('/my_url/', {self.fil_value_param: 'up',
|
||||
self.fil_field_param: 'status'})
|
||||
req.user = self.user
|
||||
view = self._test_filter_setup_view(req)
|
||||
data = view.get_data()
|
||||
context = view.get_context_data()
|
||||
self.assertEqual(context['table'].__class__, MyServerFilterTable)
|
||||
data = view.get_data()
|
||||
self.assertQuerysetEqual(data,
|
||||
['<FakeObject: object_1>',
|
||||
'<FakeObject: object_2>',
|
||||
'<FakeObject: object_3>'])
|
||||
self.assertEqual(req.session.get(filter_value_param), 'up')
|
||||
self.assertEqual(req.session.get(filter_field_param), 'status')
|
||||
self.assertEqual(req.session.get(self.fil_value_param), 'up')
|
||||
self.assertEqual(req.session.get(self.fil_field_param), 'status')
|
||||
|
||||
def test_filter_changed_deleted(self):
|
||||
req = self.factory.post('/my_url/', {self.fil_value_param: '',
|
||||
self.fil_field_param: 'status'})
|
||||
req.session[self.fil_value_param] = 'up'
|
||||
req.session[self.fil_field_param] = 'status'
|
||||
req.user = self.user
|
||||
view = self._test_filter_setup_view(req)
|
||||
context = view.get_context_data()
|
||||
self.assertEqual(context['table'].__class__, MyServerFilterTable)
|
||||
self.assertEqual(req.session.get(self.fil_value_param), '')
|
||||
self.assertEqual(req.session.get(self.fil_field_param), 'status')
|
||||
|
||||
def test_filter_changed_nothing_sent(self):
|
||||
req = self.factory.post('/my_url/', {})
|
||||
req.session[self.fil_value_param] = 'up'
|
||||
req.session[self.fil_field_param] = 'status'
|
||||
req.user = self.user
|
||||
view = self._test_filter_setup_view(req)
|
||||
context = view.get_context_data()
|
||||
self.assertEqual(context['table'].__class__, MyServerFilterTable)
|
||||
self.assertEqual(req.session.get(self.fil_value_param), 'up')
|
||||
self.assertEqual(req.session.get(self.fil_field_param), 'status')
|
||||
|
||||
def test_filter_changed_new_filter_sent(self):
|
||||
req = self.factory.post('/my_url/', {self.fil_value_param: 'down',
|
||||
self.fil_field_param: 'status'})
|
||||
req.session[self.fil_value_param] = 'up'
|
||||
req.session[self.fil_field_param] = 'status'
|
||||
req.user = self.user
|
||||
view = self._test_filter_setup_view(req)
|
||||
context = view.get_context_data()
|
||||
self.assertEqual(context['table'].__class__, MyServerFilterTable)
|
||||
self.assertEqual(req.session.get(self.fil_value_param), 'down')
|
||||
self.assertEqual(req.session.get(self.fil_field_param), 'status')
|
||||
|
||||
|
||||
class FormsetTableTests(test.TestCase):
|
||||
|
|
|
@ -90,7 +90,7 @@ class AdminInstanceFilterAction(tables.FilterAction):
|
|||
# session property used for persisting the filter.
|
||||
name = "filter_admin_instances"
|
||||
filter_type = "server"
|
||||
filter_choices = (('project', _("Project"), False),
|
||||
filter_choices = (('project', _("Project"), True),
|
||||
('host', _("Host ="), True),
|
||||
('name', _("Name"), True),
|
||||
('ip', _("IPv4 Address ="), True),
|
||||
|
@ -99,16 +99,6 @@ class AdminInstanceFilterAction(tables.FilterAction):
|
|||
('image', _("Image ID ="), True),
|
||||
('flavor', _("Flavor ID ="), True))
|
||||
|
||||
def filter(self, table, instances, filter_string):
|
||||
"""Server side search.
|
||||
When filtering is supported in the api, then we will handle in view
|
||||
"""
|
||||
filter_field = table.get_filter_field()
|
||||
if filter_field == 'project' and filter_string:
|
||||
return [inst for inst in instances
|
||||
if inst.tenant_name == filter_string]
|
||||
return instances
|
||||
|
||||
|
||||
class AdminInstancesTable(tables.DataTable):
|
||||
TASK_STATUS_CHOICES = (
|
||||
|
|
|
@ -73,6 +73,24 @@ class AdminIndexView(tables.DataTableView):
|
|||
marker = self.request.GET.get(
|
||||
project_tables.AdminInstancesTable._meta.pagination_param, None)
|
||||
search_opts = self.get_filters({'marker': marker, 'paginate': True})
|
||||
# Gather our tenants to correlate against IDs
|
||||
try:
|
||||
tenants, has_more = api.keystone.tenant_list(self.request)
|
||||
except Exception:
|
||||
tenants = []
|
||||
msg = _('Unable to retrieve instance project information.')
|
||||
exceptions.handle(self.request, msg)
|
||||
|
||||
if 'project' in search_opts:
|
||||
ten_filter_ids = [t.id for t in tenants
|
||||
if t.name == search_opts['project']]
|
||||
del search_opts['project']
|
||||
if len(ten_filter_ids) > 0:
|
||||
search_opts['tenant_id'] = ten_filter_ids[0]
|
||||
else:
|
||||
self._more = False
|
||||
return []
|
||||
|
||||
try:
|
||||
instances, self._more = api.nova.server_list(
|
||||
self.request,
|
||||
|
@ -99,14 +117,6 @@ class AdminIndexView(tables.DataTableView):
|
|||
# If fails to retrieve flavor list, creates an empty list.
|
||||
flavors = []
|
||||
|
||||
# Gather our tenants to correlate against IDs
|
||||
try:
|
||||
tenants, has_more = api.keystone.tenant_list(self.request)
|
||||
except Exception:
|
||||
tenants = []
|
||||
msg = _('Unable to retrieve instance project information.')
|
||||
exceptions.handle(self.request, msg)
|
||||
|
||||
full_flavors = SortedDict([(f.id, f) for f in flavors])
|
||||
tenant_dict = SortedDict([(t.id, t) for t in tenants])
|
||||
# Loop through instances to get flavor and tenant info.
|
||||
|
|
Loading…
Reference in New Issue