Django’s Pretty Error Pages

Take a moment to admire the fine web application we’ve made so far – now let’s break it! Let’s deliberately introduce a Python error into our views.py file by commenting out the offset = int(offset) lines in the hours_ahead view:

def hours_ahead(request, offset):

# try:

#     offset = int(offset)

# except ValueError:

#     raise Http404()

dt = datetime.datetime.now() + datetime.timedelta(hours=offset)

html = “<html><body>In %s hour(s), it will be  %s.</body></html>” %

(offset, dt)

return HttpResponse(html)

Load up the development server and navigate to /time/plus/3/. You’ll see an error page with a significant amount of information, including a TypeError message displayed at the very top: “unsupported type for timedelta hours component: str”

What happened? Well, the datetime.timedelta function expects the hours parameter to be an integer, and we commented out the bit of code that converted offset to an integer. That caused datetime.timedelta to raise the TypeError. It’s the typical kind of small bug that every programmer runs into at some point.

The point of this example was to demonstrate Django’s error pages. Take some time to explore the error page and get to know the various bits of information it gives you. Here are some things to notice:

  • At the top of the page, you get the key information about the exception: the type of exception, any parameters to the exception (the “unsupported type” message in this case), the file in which the exception was raised, and the offending line number.
  • Under the key exception information, the page displays the full Python traceback for this exception. This is similar to the standard traceback you get in Python’s command-line interpreter, except it’s more interactive. For each level (“frame”) in the stack, Django displays the name of the file, the function/method name, the line number, and the source code of that line.
  • Click the line of source code (in dark gray), and you’ll see several lines from before and after the erroneous line, to give you context. Click “Local vars” under any frame in the stack to view a table of all local variables and their values, in that frame, at the exact point in the code at which the exception was raised. This debugging information can be a great help.
  • Note the “Switch to copy-and-paste view” text under the “Traceback” header. Click those words, and the traceback will switch to an alternate version that can be easily copied and pasted. Use this when you want to share your exception traceback with others to get technical support – such as the kind folks in the Django IRC chat room or on the Django users mailing list.
  • Underneath, the “Share this traceback on a public web site” button will do this work for you in just one click. Click it to post the traceback to dpaste, where you’ll get a distinct URL that you can share with other people.
  • Next, the “Request information” section includes a wealth of information about the incoming web request that spawned the error: GET and POST information, cookie values, and meta information, such as CGI headers. Appendix F has a complete reference of all the information a request object contains.
  • Below the “Request information” section, the “Settings” section lists all of the settings for this particular Django installation.

The Django error page is capable of displaying more information in certain special cases, such as the case of template syntax errors. We’ll get to those later, when we discuss the Django template system. For now, uncomment the offset = int(offset) lines to get the view function working properly again.

The Django error page is also really useful if you are the type of programmer who likes to debug with the help of carefully placed print statements.

At any point in your view, temporarily insert an assert False to trigger the error page. Then, you can view the local variables and state of the program. Here’s an example, using the hours_ahead view:

  def hours_ahead(request, offset):   

      try:       

          offset = int(offset)    

       except ValueError:        

           raise Http404()   

       dt = datetime.datetime.now() + datetime.timedelta(hours=offset)    

      assert False    

      html = "<html><body>In %s hour(s), it will be  %s.</body></html>" % 

(offset, dt)    

  return HttpResponse(html)

Finally, it’s obvious that much of this information is sensitive – it exposes the innards of your Python code and Django configuration – and it would be foolish to show this information on the public Internet. A malicious person could use it to attempt to reverse-engineer your web application and do nasty things.

Back to Tutorial

Share this post
[social_warfare]
Your Second View: Dynamic URLs
The Django Template System

Get industry recognized certification – Contact us

keyboard_arrow_up