File: processors.py

package info (click to toggle)
python-django-feincms 1.6.2-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 2,716 kB
  • sloc: python: 6,585; makefile: 85; sh: 18
file content (141 lines) | stat: -rw-r--r-- 4,736 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import sys

from django.conf import settings as django_settings
from django.http import Http404, HttpResponseRedirect


def require_path_active_request_processor(page, request):
    """
    Checks whether any ancestors are actually inaccessible (ie. not
    inactive or expired) and raise a 404 if so.
    """
    if not page.are_ancestors_active():
        raise Http404()


def redirect_request_processor(page, request):
    """
    Returns a ``HttpResponseRedirect`` instance if the current page says
    a redirect should happen.
    """
    target = page.get_redirect_to_target(request)
    if target:
        if request._feincms_extra_context.get('extra_path', '/') == '/':
            return HttpResponseRedirect(target)
        raise Http404()

def frontendediting_request_processor(page, request):
    """
    Sets the frontend editing state in the session depending on the
    ``frontend_editing`` GET parameter and the user's permissions.
    """
    if not 'frontend_editing' in request.GET:
        return

    if request.user.has_module_perms('page'):
        try:
            enable_fe = int(request.GET['frontend_editing']) > 0
        except ValueError:
            enable_fe = False

    response = HttpResponseRedirect(request.path)
    response.set_cookie('frontend_editing', enable_fe)

    # Redirect to cleanup URLs
    return response


def etag_request_processor(page, request):
    """
    Short-circuits the request-response cycle if the ETag matches.
    """

    # XXX is this a performance concern? Does it create a new class
    # every time the processor is called or is this optimized to a static
    # class??
    class DummyResponse(dict):
        """
        This is a dummy class with enough behaviour of HttpResponse so we
        can use the condition decorator without too much pain.
        """
        def has_header(page, what):
            return False

    def dummy_response_handler(*args, **kwargs):
        return DummyResponse()

    def etagger(request, page, *args, **kwargs):
        etag = page.etag(request)
        return etag

    def lastmodifier(request, page, *args, **kwargs):
        lm = page.last_modified()
        return lm

    # Unavailable in Django 1.0 -- the current implementation of ETag support
    # requires Django 1.1 unfortunately.
    from django.views.decorators.http import condition

    # Now wrap the condition decorator around our dummy handler:
    # the net effect is that we will be getting a DummyResponse from
    # the handler if processing is to continue and a non-DummyResponse
    # (should be a "304 not modified") if the etag matches.
    rsp = condition(etag_func=etagger, last_modified_func=lastmodifier)(dummy_response_handler)(request, page)

    # If dummy then don't do anything, if a real response, return and
    # thus shortcut the request processing.
    if not isinstance(rsp, DummyResponse):
        return rsp


def etag_response_processor(page, request, response):
    """
    Response processor to set an etag header on outgoing responses.
    The Page.etag() method must return something valid as etag content
    whenever you want an etag header generated.
    """
    etag = page.etag(request)
    if etag is not None:
        response['ETag'] = '"' + etag + '"'


def debug_sql_queries_response_processor(verbose=False, file=sys.stderr):
    """
    Attaches a handler which prints the query count (and optionally all individual queries
    which have been executed) on the console. Does nothing if ``DEBUG = False``.

    Example::

        from feincms.module.page import models, processors
        models.Page.register_response_procesors(
            processors.debug_sql_queries_response_processor(verbose=True),
            )
    """
    if not django_settings.DEBUG:
        return lambda page, request, response: None

    def processor(page, request, response):
        from django.db import connection

        print_sql = lambda x: x
        try:
            import sqlparse
            print_sql = lambda x: sqlparse.format(x, reindent=True, keyword_case='upper')
        except:
            pass

        if verbose:
            print >> file, "--------------------------------------------------------------"
        time = 0.0
        i = 0
        for q in connection.queries:
            i += 1
            if verbose:
                print >> file, "%d : [%s]\n%s\n" % ( i, q['time'], print_sql(q['sql']))
            time += float(q['time'])

        print >> file, "--------------------------------------------------------------"
        print >> file, "Total: %d queries, %.3f ms" % (i, time)
        print >> file, "--------------------------------------------------------------"

    return processor