Ensures tab data is preloaded. With tests! Fixes bug 964317.
Change-Id: I55ad1e0b9b836793ee2816cec18160b223f80462
This commit is contained in:
parent
7d3a0f4d15
commit
33a0a2e401
@ -89,6 +89,7 @@ class TabGroup(html.HTMLElement):
|
|||||||
% self.__class__)
|
% self.__class__)
|
||||||
self.request = request
|
self.request = request
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
|
self._data = None
|
||||||
tab_instances = []
|
tab_instances = []
|
||||||
for tab in self.tabs:
|
for tab in self.tabs:
|
||||||
tab_instances.append((tab.slug, tab(self, request)))
|
tab_instances.append((tab.slug, tab(self, request)))
|
||||||
@ -105,7 +106,11 @@ class TabGroup(html.HTMLElement):
|
|||||||
"""
|
"""
|
||||||
for tab in self._tabs.values():
|
for tab in self._tabs.values():
|
||||||
if tab.load and not tab.data_loaded:
|
if tab.load and not tab.data_loaded:
|
||||||
tab._data = tab.get_context_data(self.request)
|
try:
|
||||||
|
tab._data = tab.get_context_data(self.request)
|
||||||
|
except:
|
||||||
|
tab._data = False
|
||||||
|
exceptions.handle(self.request)
|
||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
"""
|
"""
|
||||||
@ -262,7 +267,7 @@ class Tab(html.HTMLElement):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def data(self):
|
def data(self):
|
||||||
if not getattr(self, "_data", None):
|
if getattr(self, "_data", None) is None:
|
||||||
self._data = self.get_context_data(self.request)
|
self._data = self.get_context_data(self.request)
|
||||||
return self._data
|
return self._data
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@ class TabView(generic.TemplateView):
|
|||||||
try:
|
try:
|
||||||
tab_group = self.get_tabs(self.request, **kwargs)
|
tab_group = self.get_tabs(self.request, **kwargs)
|
||||||
context["tab_group"] = tab_group
|
context["tab_group"] = tab_group
|
||||||
|
# Make sure our data is pre-loaded to capture errors.
|
||||||
|
context["tab_group"].load_tab_data()
|
||||||
except:
|
except:
|
||||||
exceptions.handle(self.request)
|
exceptions.handle(self.request)
|
||||||
return context
|
return context
|
||||||
@ -111,12 +113,6 @@ class TabbedTableView(tables.MultiTableMixin, TabView):
|
|||||||
handled = tab._tables[table_name].maybe_handle()
|
handled = tab._tables[table_name].maybe_handle()
|
||||||
return handled
|
return handled
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
""" Adds the ``tab_group`` variable to the context data. """
|
|
||||||
context = super(TabbedTableView, self).get_context_data(**kwargs)
|
|
||||||
context['tab_group'].load_tab_data()
|
|
||||||
return context
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
self.load_tabs()
|
self.load_tabs()
|
||||||
# Gather our table instances. It's important that they're the
|
# Gather our table instances. It's important that they're the
|
||||||
|
@ -49,6 +49,12 @@ wsgi.WSGIRequest.__repr__ = lambda self: "<class 'django.http.HttpRequest'>"
|
|||||||
|
|
||||||
|
|
||||||
class RequestFactoryWithMessages(RequestFactory):
|
class RequestFactoryWithMessages(RequestFactory):
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
req = super(RequestFactoryWithMessages, self).get(*args, **kwargs)
|
||||||
|
req.session = []
|
||||||
|
req._messages = default_storage(req)
|
||||||
|
return req
|
||||||
|
|
||||||
def post(self, *args, **kwargs):
|
def post(self, *args, **kwargs):
|
||||||
req = super(RequestFactoryWithMessages, self).post(*args, **kwargs)
|
req = super(RequestFactoryWithMessages, self).post(*args, **kwargs)
|
||||||
req.session = []
|
req.session = []
|
||||||
@ -173,8 +179,13 @@ class TestCase(django_test.TestCase):
|
|||||||
if 'messages' in self.client.cookies:
|
if 'messages' in self.client.cookies:
|
||||||
message_cookie = self.client.cookies['messages'].value
|
message_cookie = self.client.cookies['messages'].value
|
||||||
messages = storage._decode(message_cookie)
|
messages = storage._decode(message_cookie)
|
||||||
elif "messages" in response.context:
|
# Check for messages in the context
|
||||||
|
elif hasattr(response, "context") and "messages" in response.context:
|
||||||
messages = response.context["messages"]
|
messages = response.context["messages"]
|
||||||
|
# Check for messages attached to the request on a TemplateResponse
|
||||||
|
elif hasattr(response, "_request") and hasattr(response._request,
|
||||||
|
"_messages"):
|
||||||
|
messages = response._request._messages._queued_messages
|
||||||
|
|
||||||
# If we don't have messages and we don't expect messages, we're done.
|
# If we don't have messages and we don't expect messages, we're done.
|
||||||
if not any(kwargs.values()) and not messages:
|
if not any(kwargs.values()) and not messages:
|
||||||
|
@ -14,9 +14,12 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import copy
|
||||||
|
|
||||||
from django import http
|
from django import http
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from horizon import exceptions
|
||||||
from horizon import tabs as horizon_tabs
|
from horizon import tabs as horizon_tabs
|
||||||
from horizon import test
|
from horizon import test
|
||||||
|
|
||||||
@ -77,9 +80,19 @@ class TabWithTable(horizon_tabs.TableTab):
|
|||||||
return TEST_DATA
|
return TEST_DATA
|
||||||
|
|
||||||
|
|
||||||
|
class RecoverableErrorTab(horizon_tabs.Tab):
|
||||||
|
name = _("Recoverable Error Tab")
|
||||||
|
slug = "recoverable_error_tab"
|
||||||
|
template_name = "_tab.html"
|
||||||
|
|
||||||
|
def get_context_data(self, request):
|
||||||
|
# Raise a known recoverable error.
|
||||||
|
raise exceptions.AlreadyExists("Recoverable!", None)
|
||||||
|
|
||||||
|
|
||||||
class TableTabGroup(horizon_tabs.TabGroup):
|
class TableTabGroup(horizon_tabs.TabGroup):
|
||||||
slug = "tab_group"
|
slug = "tab_group"
|
||||||
tabs = (TabWithTable,)
|
tabs = [TabWithTable]
|
||||||
|
|
||||||
|
|
||||||
class TabWithTableView(horizon_tabs.TabbedTableView):
|
class TabWithTableView(horizon_tabs.TabbedTableView):
|
||||||
@ -88,9 +101,6 @@ class TabWithTableView(horizon_tabs.TabbedTableView):
|
|||||||
|
|
||||||
|
|
||||||
class TabTests(test.TestCase):
|
class TabTests(test.TestCase):
|
||||||
def setUp(self):
|
|
||||||
super(TabTests, self).setUp()
|
|
||||||
|
|
||||||
def test_tab_group_basics(self):
|
def test_tab_group_basics(self):
|
||||||
tg = Group(self.request)
|
tg = Group(self.request)
|
||||||
|
|
||||||
@ -265,3 +275,26 @@ class TabTests(test.TestCase):
|
|||||||
res = view(req)
|
res = view(req)
|
||||||
self.assertEqual(res.status_code, 302)
|
self.assertEqual(res.status_code, 302)
|
||||||
self.assertEqual(res["location"], "/")
|
self.assertEqual(res["location"], "/")
|
||||||
|
|
||||||
|
# Ensure that lookup errors are raised as such instead of converted
|
||||||
|
# to TemplateSyntaxErrors.
|
||||||
|
action_string = "my_table__toggle__2000000000"
|
||||||
|
req = self.factory.post('/', {'action': action_string})
|
||||||
|
self.assertRaises(exceptions.Http302, view, req)
|
||||||
|
|
||||||
|
|
||||||
|
class TabExceptionTests(test.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TabExceptionTests, self).setUp()
|
||||||
|
self._original_tabs = copy.copy(TabWithTableView.tab_group_class.tabs)
|
||||||
|
TabWithTableView.tab_group_class.tabs.append(RecoverableErrorTab)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TabExceptionTests, self).tearDown()
|
||||||
|
TabWithTableView.tab_group_class.tabs = self._original_tabs
|
||||||
|
|
||||||
|
def test_tab_view_exception(self):
|
||||||
|
view = TabWithTableView.as_view()
|
||||||
|
req = self.factory.get("/")
|
||||||
|
res = view(req)
|
||||||
|
self.assertMessageCount(res, error=1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user