Previous Page Next Page

Implementing a View Preprocessor

You implement a view preprocessor by defining a process_view(self, request, view, args, kwargs) function in the middleware class. The process_view() function is called after the URL has been resolved to determine which view function and arguments to run, but before the view function is called.

The process_view() function is passed the HttpRequest object, view function, positional arguments, and keyword arguments. Any changes you make to the HttpRequest object also are passed down to the view function. The process_view() function is an excellent way to make modifications globally to define specific arguments to all view functions.

The process_view() function can also return either None or an HttpResponse object. If None is returned, Django continues processing the request and calls the view function. However, if you return an HttpResponse object, the request immediately returns that response.

Watch Out!

No other middleware applications or view functions will run if an HttpResponse is returned.


The following code snippet sets the Logging argument to True for all view functions' proxies:

class ViewLogging(object):
    def process_view(self, request, view, args, kwargs):
        try:
            kwargs['Logging'] = True
        except KeyError:
            pass

        return None

Try It Yourself: Create and Install a View Preprocessor Middleware Application

In this section, you will create and install a view preprocessor application called CustomViewLogger that logs information about view functions before they are run. You will define a new ViewEvent model in the Log application to store information about view functions that are called. You will also create a template that the view_log() view function will use to render the ViewEvent objects:

Follow these steps to implement a view preprocessor middleware application:

1.
Stop the development server.

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

3.
Add the ViewEvent model to the file, as shown in Listing 19.5, to define a ViewEvent object that can store information about the view that is being rendered.

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.6, to import the ViewEvent object you defined in step 3:

from iFriends.Log.models import ViewEvent

8.
Add the CustomViewLogger middleware class definition to the file and define the process_view() function, as shown in Listing 19.6. This will collect information about the view request and store it in a ViewEvent object in the database.

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

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

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

12.
Save the iFriends/templates/Custom/view_view_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, shown in Listing 19.8. It sets lTemplate to the view_view_log.html file and logList to the ViewEvent objects if evType is set to view:

if evType == "view":
    lTemplate = 'Custom/view_view_log.html'
    logList = ViewEvent.objects.all()
else:

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 CustomViewLogger application:

'django.middleware.custom.CustomViewLogger',

18.
Save the iFriends/settings.py file.

19.
Start the development server.

20.
Access several nonadmin web pages in the iFriends site, and then access the following URL to view the log report, as shown in Figure 19.2, generated by the CustomViewLogger application:

http://127.0.0.1:8000/admin/view_log/view/

Figure 19.2. The view_log() function displaying the ViewEvent log.


Listing 19.5. The ViewEvent Definition of the iFriends/Log/models.py File

class ViewEvent(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)
    view = models.CharField('View', max_length=80)
    args = models.TextField('Args', max_length=200)
    kwargs = models.TextField('KWArgs', max_length=400)

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

    class Admin:
        pass

Listing 19.6. The Imports and CustomViewLogger Definition of the django/middleware/custom.py File

from iFriends.Log.models import ViewEvent
. . .
class CustomViewLogger(object):
    def process_view(self, request, view, args, kwargs):
        try:
            if not request.META['PATH_INFO'].startswith('/admin'):
                event = ViewEvent()
                event.event = "View"
                event.user = request.user
                event.addr = request.META['REMOTE_ADDR']
                event.date = datetime.now()
                event.view = view.__name__
                event.args = str(args)
                event.kwargs = str(kwargs)
                event.save()
        except KeyError:
            pass
        return None

Listing 19.7. Full Contents of the iFriends/templates/Custom/view_view_log.py File

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

{% block content %}
<h1>View Log Report</h1>
<table>
<tr>
<th>Date</th><th>User</th><th>IP Address</th><th>View</th><th>Args</th>
   <th>KWArgs</th>
</tr>
{% for entry in logList %}
    <tr>
        <td>{{ entry.date }}</td>
        <td>{{ entry.user }}</td>
        <td>{{ entry.addr }}</td>
        <td>{{ entry.view }}</td>
        <td>{{ entry.args }}</td>
        <td>{{ entry.kwargs }}</td>
    </tr>
{% endfor %}
</table>
{% endblock %}

Listing 19.8. 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()
    else:
        lTemplate = 'Custom/view_request_log.html'
        logList = RequestEvent.objects.all()

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


Previous Page Next Page