Previous Page Next Page

Implementing an Exception Postprocessor

You implement an exception postprocessor by defining a process_exception (self, request, exception) function in the middleware class. The process_exception() function is called if an exception was raised by the view and was not handled.

By the Way

The process_exception() function is not called on Http404 exceptions.


The process_exception() function is passed the HttpRequest object and an Exception object arguments. Using the process_exception() function, you may be able to handle some exceptions and recover so that the browser doesn't receive an error. You can also use the process_exception() function to log and debug errors on the website.

The process_response() function can return None or an HttpResponse object. If None is returned, Django continues processing the exception using its built-in exception handling. If you pass back an HttpResponse object, the browser receives that response instead of an error.

For example, the following code snippet intercepts any unhandled exceptions and calls a HandleErrors() view function that returns some kind of HttpResponse:

from mySite.custom.views import HandleErrors
class AddFooter(object):
    def process_exception(self, request, exception):
        return HandleErrors(request, exception)

Try It Yourself: Create and Install an Exception Postprocessor Middleware Application

In this section, you will create and install an exception postprocessor application called CustomExceptionLogger. It will log information about exceptions that are not handled and, therefore, are sent to the browser. You will also define a new ExceptionEvent model in the Log application to store information about the exception before an error is sent back to the browser. You will also create a template that the view_log() view function will use to render the ExceptionEvent objects:

Follow these steps to implement the exception postprocessor middleware application:

1.
Stop the development server.

2.
Open the iFriends/Log/models.py file in an editor.

3.
Add the ExceptionEvent model to the file, as shown in Listing 19.13, to define an ExceptionEvent object that can store information about the exception.

4.
Save the iFriends/Log/models.py file.

5.
Synchronize the database using the manage.py syncdb command from the root of the iFriends project.

6.
Open the django/middleware/custom.py file in your Django installation.

7.
Add the following import to the file, as shown in Listing 19.14, to import the ExceptionEvent object you defined in step 3:

from iFriends.Log.models import ExceptionEvent

8.
Add the CustomExceptionLogger middleware class definition to the file, and define the process_exception() function, as shown in Listing 19.14. It collects information about the view request and stores it in an ExceptionEvent object in the database.

9.
Save the django/middleware/custom.py file.

10.
Create and open a file called iFriends/templates/Custom/view_event_log.html in an editor.

11.
Add the contents shown in Listing 19.15 to the file.

12.
Save the iFriends/templates/Custom/view_event_log.html file.

13.
Open the iFriends/Custom/views.py file in an editor.

14.
Add the following code to the view_log() view function, as shown in Listing 19.16, to set lTemplate to the view_exception_log.html file and logList to the ExceptionEvent objects if evType is set to exception:

elif evType == "response":
    lTemplate = 'Custom/view_response_log.html'
    logList = ViewResponse.objects.all()

15.
Save the iFriends/Custom/views.py file.

16.
Open the iFriends/settings.py file in an editor.

17.
Add the following line to the MIDDLEWARE_CLASSES setting to install the CustomExceptionLogger application:

'django.middleware.custom.CustomExceptionLogger',

18.
Save the iFriends/settings.py file.

19.
Start the development server.

20.
You need to access URLs that generate exceptions in the iFriends site (you can also force exceptions in your view code). Then access the following URL to view the exception log report, as shown in Figure 19.4, generated by the CustomExceptionLogger application:

http://127.0.0.1:8000/admin/view_log/exception/

Figure 19.4. The view_log() function displaying the ExceptionEvent log.


Listing 19.13. The ExceptionEvent Definition of the iFriends/Log/models.py File

class ExceptionEvent(models.Model):
    event = models.CharField('Event', max_length=30)
    date = models.DateTimeField('Date')
    user = models.ForeignKey(User)
    addr = models.CharField('IP Address', max_length=20)
    url = models.CharField('Url', max_length=80)
    exception = models.CharField('Exception', max_length=100)

    def __str__(self):
        return '%s - %s' % (self.event, self.date)

    class Admin:
        pass

Listing 19.14. The Imports and CustomExceptionLogger Definition of the django/middleware/custom.py File

from iFriends.Log.models import ExceptionEvent
. . .
class CustomExceptionLogger(object):
    def process_exception(self, request, exception):
        try:
            if not request.META['PATH_INFO'].startswith('/admin'):
                event = ExceptionEvent()
                event.event = "Exception"
                event.user = request.user
                event.addr = request.META['REMOTE_ADDR']
                event.date = datetime.now()
                event.url = request.META['PATH_INFO']
                event.exception = exception
                event.save()
        except KeyError:
            pass
        return None

Listing 19.15. Full Contents of the iFriends/templates/Custom/view_exception_log.py File

{% extends "admin/base_site.html" %}
{% block title %}Exception Log Report{% endblock %}

{% block content %}
<h1>Exception Log Report</h1>
<table>
<tr>
<th>Date</th><th>User</th><th>IP Address</th><th>URL</th><th>Exception</th>
</tr>
{% for entry in logList %}
    <tr>
        <td>{{ entry.date }}</td>
        <td>{{ entry.user }}</td>
        <td>{{ entry.addr }}</td>
        <td>{{ entry.url }}</td>
        <td>{{ entry.exception }}</td>
    </tr>
{% endfor %}
</table>
{% endblock %}

Listing 19.16. The view_log() View Function of the iFriends/Custom/views.py File

@staff_member_required
def view_log(request, evType='request'):
    if evType == "view":
        lTemplate = 'Custom/view_view_log.html'
        logList = ViewEvent.objects.all()
    elif evType == "response":
        lTemplate = 'Custom/view_response_log.html'
        logList = ResponseEvent.objects.all()
    elif evType == "exception":
        lTemplate = 'Custom/view_exception_log.html'
        logList = ExceptionEvent.objects.all()
    else:
        lTemplate = 'Custom/view_request_log.html'
        logList = RequestEvent.objects.all()

    return render_to_response(lTemplate, {'logList': logList})


Previous Page Next Page