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.request = request
|
||||
self.kwargs = kwargs
|
||||
self._data = None
|
||||
tab_instances = []
|
||||
for tab in self.tabs:
|
||||
tab_instances.append((tab.slug, tab(self, request)))
|
||||
@ -105,7 +106,11 @@ class TabGroup(html.HTMLElement):
|
||||
"""
|
||||
for tab in self._tabs.values():
|
||||
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):
|
||||
"""
|
||||
@ -262,7 +267,7 @@ class Tab(html.HTMLElement):
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
if not getattr(self, "_data", None):
|
||||
if getattr(self, "_data", None) is None:
|
||||
self._data = self.get_context_data(self.request)
|
||||
return self._data
|
||||
|
||||
|
@ -38,6 +38,8 @@ class TabView(generic.TemplateView):
|
||||
try:
|
||||
tab_group = self.get_tabs(self.request, **kwargs)
|
||||
context["tab_group"] = tab_group
|
||||
# Make sure our data is pre-loaded to capture errors.
|
||||
context["tab_group"].load_tab_data()
|
||||
except:
|
||||
exceptions.handle(self.request)
|
||||
return context
|
||||
@ -111,12 +113,6 @@ class TabbedTableView(tables.MultiTableMixin, TabView):
|
||||
handled = tab._tables[table_name].maybe_handle()
|
||||
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):
|
||||
self.load_tabs()
|
||||
# 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):
|
||||
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):
|
||||
req = super(RequestFactoryWithMessages, self).post(*args, **kwargs)
|
||||
req.session = []
|
||||
@ -173,8 +179,13 @@ class TestCase(django_test.TestCase):
|
||||
if 'messages' in self.client.cookies:
|
||||
message_cookie = self.client.cookies['messages'].value
|
||||
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"]
|
||||
# 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 not any(kwargs.values()) and not messages:
|
||||
|
@ -14,9 +14,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from django import http
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs as horizon_tabs
|
||||
from horizon import test
|
||||
|
||||
@ -77,9 +80,19 @@ class TabWithTable(horizon_tabs.TableTab):
|
||||
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):
|
||||
slug = "tab_group"
|
||||
tabs = (TabWithTable,)
|
||||
tabs = [TabWithTable]
|
||||
|
||||
|
||||
class TabWithTableView(horizon_tabs.TabbedTableView):
|
||||
@ -88,9 +101,6 @@ class TabWithTableView(horizon_tabs.TabbedTableView):
|
||||
|
||||
|
||||
class TabTests(test.TestCase):
|
||||
def setUp(self):
|
||||
super(TabTests, self).setUp()
|
||||
|
||||
def test_tab_group_basics(self):
|
||||
tg = Group(self.request)
|
||||
|
||||
@ -265,3 +275,26 @@ class TabTests(test.TestCase):
|
||||
res = view(req)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
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…
Reference in New Issue
Block a user