Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to get fail_on_template_errors working with class based views #5

Open
clokep opened this issue May 25, 2016 · 4 comments
Open

Comments

@clokep
Copy link
Contributor

clokep commented May 25, 2016

I've been unable to get this to work with class based views (well without calling render_to_string manually in a CBV, which kind of defeats the purpose).

I was hoping to do something like:

from pedant.decorators import fail_on_template_errors

class MyView(TemplateView):
    template_name = 'my_view.html'

    @fail_on_template_errors
    def render_to_response(self, *args, **kwargs):
        return super(MyView, self).render_to_response(*args, **kwargs)

I don't see how the TemplateResponse code differs much from render_to_string, but I've been unable to get this to work. Is there a fundamental flaw that this doesn't work on CBVs or am I doing something wrong?

Thanks!

(If this worked, it might make a nice mixin to include, or at least document!)

@lucaswiman
Copy link
Contributor

@clokep Could you post the stack trace and also the Django version you're using?

@clokep
Copy link
Contributor Author

clokep commented May 25, 2016

@lucaswiman There's no stack trace (that's the problem 😉).

I'm on Django 1.9.6.

My template:

This is a template {{ foo }}

The view:

from pedant.decorators import fail_on_template_errors

class MyView(TemplateView):
    template_name = 'test.html'

    @fail_on_template_errors
    def render_to_response(self, *args, **kwargs):
        return super(MyView, self).render_to_response(*args, **kwargs)

The result is that I see a page that says "This is a template ", I expected an exception.

@lucaswiman
Copy link
Contributor

As far as I can tell, the issue is that class-based views use a lazy-rendering TemplateResponse object, which (despite the name) isn't actually rendered in render_to_response. I think you'd need to subclass TemplateResponse and override its .render() method, then set that as the response_class:

from django.template.response import *
class PedanticTemplateResponse(TemplateResponse):
    @fail_on_template_errors
    def render(self, *args, **kwargs):
        return super(PedanticTemplateResponse, self).render(self, *args, **kwargs)

class MyView(TemplateView):
    response_class = PedanticTemplateResponse

If you want to add this or documentation for using CBVs, pull requests are definitely welcome. Personally, little gotchas like this are why I try to avoid CBVs.

@clokep
Copy link
Contributor Author

clokep commented May 26, 2016

Thanks for the hints! I forgot templates get rendered in middleware.

A less clean solution that requires less overwriting would be:

from pedant.decorators import fail_on_template_errors

class MyView(TemplateView):
    template_name = 'test.html'

    @fail_on_template_errors
    def render_to_response(self, *args, **kwargs):
        result = super(MyView, self).render_to_response(*args, **kwargs)
        result.render()
        return result

There's a minor bug in your code, by the way, render shouldn't have self as an argument.

I'll try to put up a PR for this soon!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants