18

I have a custom 404 view defined in my Pyramid app:

@view_config(context=HTTPNotFound, renderer='404.pt')
def not_found(self, request):
     return {}

It works fine, except that the HTTP status code sent with the content is 200 OK, which is not OK by any means. I'm having the same problem with 403 Forbidden. How can I get Pyramid to send the correct status code?

Theron Luhn
  • 3,974
  • 4
  • 37
  • 49

4 Answers4

21

The exception view is a separate view that provides a spot for you to do whatever you want. Just like any view that uses a renderer, you can affect the response object via request.response to modify its behavior. The renderer then fills in the body.

@view_config(context=HTTPNotFound, renderer='404.pt')
def not_found(self, request):
    request.response.status = 404
    return {}
Michael Merickel
  • 23,153
  • 3
  • 54
  • 70
  • 2
    Perfect! However, one correction: the status should be '404 Not Found'. From the Pyramid docs: "response.status -- The response code plus reason message, like '200 OK'. To set the code without a message, use status_int, i.e.: response.status_int = 200." – Theron Luhn Mar 22 '12 at 02:41
  • 4
    If you set it as an integer, it will look up the status in its internal lookup table and fill in the string for you. It's a convenience wrinkle that probably should be documented better. – Michael Merickel Mar 22 '12 at 03:56
8

Actually, in pyramid 1.3 There's a new decorator @notfound_view_config.

@notfound_view_config(renderer = '404_error.jinja2')
def notfound(request):
    request.response.status = 404
ajorquera
  • 1,297
  • 22
  • 29
0

Here is how you can directly use the 404 hook and render a template while doing so.

In your init.py:

config.add_notfound_view(not_found)

In your view.py:

from pyramid.view import notfound_view_config
from pyramid.renderers import render_to_response

def not_found(request):
    request.response.status = 404
    t = 'talk_python_to_me_com:templates/errors/404.pt'
    return render_to_response(t, {}, request)

I did this for Talk Python To Me: http://www.talkpythontome.com/, here's an invalid page to see a custom template rendered.

http://www.talkpythontome.com/there_is_no_cat

Michael Kennedy
  • 3,202
  • 2
  • 25
  • 34
0

The best way to do this is to override the default Not Found View:

http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/hooks.html#changing-the-not-found-view

Even in this scenario, you need to return a proper response object which has a status of 404:

def notfound(request):
    return Response('Not Found, dude', status='404 Not Found')

To take the example from the page linked above

turtlebender
  • 1,907
  • 15
  • 16
  • But that doesn't let me use a Chameleon template... :( – Theron Luhn Mar 22 '12 at 01:43
  • you can either, render the template yourself, or, I believe that the chameleon renderer will let you return a Response object and then process the body via the template. so, if you do what you posted above, but then do return Response(status='404 Not Found'), I believe it will render an empty dict via chameleon with the proper response code – turtlebender Mar 22 '12 at 02:19