diff --git a/horizon/test/tests/views.py b/horizon/test/tests/views.py index edfcc6bd06..86b5e5c9df 100644 --- a/horizon/test/tests/views.py +++ b/horizon/test/tests/views.py @@ -18,6 +18,7 @@ from horizon import views from django import forms from django.test import client +from django.utils.translation import ugettext_lazy as _ from django.views import generic FAKENAME = "FakeName" @@ -54,6 +55,10 @@ class ViewWithTitle(views.PageTitleMixin, generic.TemplateView): page_title = "Fake" +class ViewWithTransTitle(views.PageTitleMixin, generic.TemplateView): + page_title = _("Fake") + + class PageTitleTests(test.TestCase): def setUp(self): @@ -65,16 +70,21 @@ class PageTitleTests(test.TestCase): p.request = self.request return p.dispatch(self.request) - def test_render_title(self): + def test_render_context_with_title(self): tm = ViewWithTitle() - context = tm.render_title({}) + context = tm.render_context_with_title({}) self.assertEqual("Fake", context['page_title']) - def test_render_title_override(self): + def test_render_context_with_title_override(self): tm = ViewWithTitle() - context = tm.render_title({'page_title': "ekaF"}) + context = tm.render_context_with_title({'page_title': "ekaF"}) self.assertEqual("ekaF", context['page_title']) + def test_render_context_with_title_lazy_translations(self): + tm = ViewWithTransTitle() + context = tm.render_context_with_title({}) + self.assertEqual("Fake", context['page_title']) + def test_no_title_set(self): res = self._dispatch(PageWithNoTitle) self.assertEqual("", res.context_data['page_title']) diff --git a/horizon/views.py b/horizon/views.py index 5aadaefd40..9da293d33e 100644 --- a/horizon/views.py +++ b/horizon/views.py @@ -14,6 +14,7 @@ from django import shortcuts from django import template +from django.utils import encoding from django.views import generic import horizon @@ -21,19 +22,46 @@ from horizon import exceptions class PageTitleMixin(object): + """A mixin that renders out a page title into a view. + + Many views in horizon have a page title that would ordinarily be + defined and passed through in get_context_data function, this often + leads to a lot of duplicated work in each view. + + This mixin standardises the process of defining a page title, letting + views simply define a variable that is rendered into the context for + them. + + There are cases when page title in a view may also display some context + data, for that purpose the page_title variable supports the django + templating language and will be rendered using the context defined by the + views get_context_data. + """ + page_title = "" - def render_title(self, context): + def render_context_with_title(self, context): + """This function takes in a context dict and uses it to render the + page_title variable, it then appends this title to the context using + the 'page_title' key. If there is already a page_title key defined in + context received then this function will do nothing. + """ + if "page_title" not in context: con = template.Context(context) - # NOTE(sambetts): Cast to unicode to ensure lazy translations + # NOTE(sambetts): Use force_text to ensure lazy translations # are handled correctly. - temp = template.Template(unicode(self.page_title)) + temp = template.Template(encoding.force_text(self.page_title)) context["page_title"] = temp.render(con) return context def render_to_response(self, context): - context = self.render_title(context) + """This is an override of the default render_to_response function that + exists in the django generic views, this is here to inject the + page title into the context before the main template is rendered. + """ + + context = self.render_context_with_title(context) return super(PageTitleMixin, self).render_to_response(context) diff --git a/openstack_dashboard/usage/views.py b/openstack_dashboard/usage/views.py index 0afa926de9..bd10ad00df 100644 --- a/openstack_dashboard/usage/views.py +++ b/openstack_dashboard/usage/views.py @@ -73,7 +73,7 @@ class UsageView(tables.DataTableView): response_kwargs.setdefault("filename", "usage.csv") else: render_class = self.response_class - context = self.render_title(context) + context = self.render_context_with_title(context) resp = render_class(request=self.request, template=self.get_template_names(), context=context,