diff --git a/README.rst b/README.rst index b399075..17b041d 100644 --- a/README.rst +++ b/README.rst @@ -57,4 +57,20 @@ the decorator:: def my_view(request): return TemplateResponse(request, "template.html", {'my': 'context'}) +If you'd like to use Django 1.3's class-based views instead, a PJAX Mixin class +is provided as well. Simply use ``PJAXResponseMixin`` where you would normally have +used ``TemplateResponseMixin``, and your ``template_name`` will be treated the same +way as above. You can alternately provide a ``pjax_template_name`` class variable +if you want a specific template used for PJAX responses:: + + from django.views.generic import View + from djpjax import PJAXResponseMixin + + class MyView(PJAXResponseMixin, View): + template_name = "template.html" + pjax_template_name = "pjax.html" + + def get(self, request): + return self.render_to_response({'my': 'context'}) + That's it! \ No newline at end of file diff --git a/djpjax.py b/djpjax.py index 57ac9fb..f8c11ef 100644 --- a/djpjax.py +++ b/djpjax.py @@ -1,5 +1,7 @@ import functools +from django.views.generic.base import TemplateResponseMixin + def pjax(pjax_template=None): def pjax_decorator(view): @functools.wraps(view) @@ -12,10 +14,38 @@ def _view(request, *args, **kwargs): if request.META.get('HTTP_X_PJAX', False): if pjax_template: resp.template_name = pjax_template - elif "." in resp.template_name: - resp.template_name = "%s-pjax.%s" % tuple(resp.template_name.rsplit('.', 1)) else: - resp.template_name += "-pjax" + resp.template_name = _pjaxify_template_var(resp.template_name) return resp return _view - return pjax_decorator \ No newline at end of file + return pjax_decorator + + +class PJAXResponseMixin(TemplateResponseMixin): + + pjax_template_name = None + + def get_template_names(self): + names = super(PJAXResponseMixin, self).get_template_names() + if self.request.META.get('HTTP_X_PJAX', False): + if self.pjax_template_name: + names = [self.pjax_template_name] + else: + names = _pjaxify_template_var(names) + return names + + +def _pjaxify_template_var(template_var): + if isinstance(template_var, (list, tuple)): + template_var = type(template_var)(_pjaxify_template_name(name) for name in template_var) + elif isinstance(template_var, basestring): + template_var = _pjaxify_template_name(template_var) + return template_var + + +def _pjaxify_template_name(name): + if "." in name: + name = "%s-pjax.%s" % tuple(name.rsplit('.', 1)) + else: + name += "-pjax" + return name diff --git a/tests.py b/tests.py index f432373..8adc639 100644 --- a/tests.py +++ b/tests.py @@ -4,6 +4,7 @@ import djpjax from django.template.response import TemplateResponse from django.test.client import RequestFactory +from django.views.generic import View # A couple of request objects - one PJAX, one not. rf = RequestFactory() @@ -30,6 +31,33 @@ def test_view_with_pjax_template(): resp = view_with_pjax_template(pjax_request) assert resp.template_name == "pjax.html" +def test_view_with_template_tuple(): + resp = view_with_template_tuple(regular_request) + assert resp.template_name == ("template.html", "other_template.html") + resp = view_with_template_tuple(pjax_request) + assert resp.template_name == ("template-pjax.html", "other_template-pjax.html") + +def test_class_pjax_sans_template(): + view = NoPJAXTemplateVew.as_view() + resp = view(regular_request) + assert resp.template_name[0] == "template.html" + resp = view(pjax_request) + assert resp.template_name[0] == "template-pjax.html" + +def test_class_with_silly_template(): + view = SillyTemplateNameView.as_view() + resp = view(regular_request) + assert resp.template_name[0] == "silly" + resp = view(pjax_request) + assert resp.template_name[0] == "silly-pjax" + +def test_class_with_pjax_template(): + view = PJAXTemplateView.as_view() + resp = view(regular_request) + assert resp.template_name[0] == "template.html" + resp = view(pjax_request) + assert resp.template_name[0] == "pjax.html" + # The test "views" themselves. @djpjax.pjax() @@ -44,3 +72,25 @@ def view_with_silly_template(request): def view_with_pjax_template(request): return TemplateResponse(request, "template.html", {}) +@djpjax.pjax() +def view_with_template_tuple(request): + return TemplateResponse(request, ("template.html", "other_template.html"), {}) + +class NoPJAXTemplateVew(djpjax.PJAXResponseMixin, View): + template_name = 'template.html' + + def get(self, request): + return self.render_to_response({}) + +class SillyTemplateNameView(djpjax.PJAXResponseMixin, View): + template_name = 'silly' + + def get(self, request): + return self.render_to_response({}) + +class PJAXTemplateView(djpjax.PJAXResponseMixin, View): + template_name = 'template.html' + pjax_template_name = 'pjax.html' + + def get(self, request): + return self.render_to_response({})