root/lib/sct/sphenecoll/sphene/community/middleware.py

Revision 169:45a1e0bafadd, 11.5 kB (checked in by Daniele Varrazzo <piro@develer.com>, 1 year ago)

imported patch cache-group.patch

Line 
1 from django.conf import settings
2 from django.conf.urls.defaults import *
3 from django.core import urlresolvers
4
5 from django.http import Http404
6 from django.shortcuts import get_object_or_404
7
8 from django.contrib.sites.models import SiteManager, Site
9
10
11 from sphene.community.models import Group, get_group
12 from sphene.community.sphsettings import get_sph_setting
13
14
15 import re
16 import logging
17
18
19 logger = logging.getLogger('sphene.community.middleware')
20
21 def my_get_current(self):
22     group = get_current_group()
23     from django.conf import settings
24     if not group:
25         return self.get(pk=settings.SITE_ID)
26     else:
27         return Site( pk=settings.SITE_ID, domain = group.baseurl, name = group.name )
28
29 SiteManager.get_current = my_get_current
30                    
31
32
33 # If all are used the following order has to remain:
34 # 1.) ThreadLocals (required)
35 # 2.) MultiHostMiddleware (optional, but very much recommended!)
36 # 3.) GroupMiddleware (required)
37 # all other orders will lead to problems ..
38
39
40 #
41 # Short descriptions:
42 #  every module within SCT requires a Group object - this can either come from the
43 #  MultiHostMiddleware - ie. from the domain/host name (vhosts) or from an URL parameter.
44 #  we need to somehow distuingish between those two within the reverse URL lookups.
45 #
46
47 class MultiHostMiddleware:
48     def process_request(self, request):
49         try:
50             sphdata = get_current_sphdata()
51             host = request.META['HTTP_HOST']
52             if host[-3:] == ':80':
53                 host = host[:-3] # ignore default port number, if present
54             urlconf = None
55             urlconf_params = None
56             if host in settings.SPH_HOST_MIDDLEWARE_URLCONF_MAP:
57                 urlconf = settings.SPH_HOST_MIDDLEWARE_URLCONF_MAP[host]
58             else:
59                 # TODO cache results ? - cache regular expressions .. ?
60                 for key, value in settings.SPH_HOST_MIDDLEWARE_URLCONF_MAP.iteritems():
61                     regex = re.compile(key)
62                     match = regex.match(host)
63                     if not match:
64                         continue
65                     # We got a match.
66                     urlconf = value
67                     urlconf_params = 'params' in urlconf and urlconf['params'].copy() or dict()
68                     namedgroups = match.groupdict()
69                     for key, value in namedgroups.iteritems():
70                         urlconf_params[key] = value
71                     break
72             if not urlconf:
73                 logging.info("Unable to find urlconf for %s / map: %s !!!" % (host, str(settings.SPH_HOST_MIDDLEWARE_URLCONF_MAP)))
74                 return
75             while 'alias' in urlconf:
76                 urlconf = settings.SPH_HOST_MIDDLEWARE_URLCONF_MAP[urlconf['alias']]
77                
78             myparams = urlconf_params or urlconf['params']
79
80             # if there is a parameter called 'groupName', load the given group,
81             # and set it into the thread locals.
82             if myparams and 'groupName' in myparams:
83                 try:
84                     set_current_group( get_group( myparams['groupName'] ) )
85                     sphdata['group_fromhost'] = True
86                 except Group.DoesNotExist:
87                     pass
88             set_current_urlconf_params( urlconf_params or urlconf['params'] )
89             request.urlconf = urlconf['urlconf']
90            
91         except KeyError:
92             pass # use default urlconf
93
94 class GroupMiddleware(object):
95     def process_view(self, request, view_func, view_args, view_kwargs):
96         request.attributes = { }
97         if 'urlPrefix' in view_kwargs:
98             urlPrefix = view_kwargs['urlPrefix']
99             if urlPrefix != '':
100                 urlPrefix = '/' + urlPrefix
101             request.attributes['urlPrefix'] = urlPrefix
102             del view_kwargs['urlPrefix']
103         group = None
104         groupName = None
105         if get_current_urlconf_params() and 'groupName' in get_current_urlconf_params():
106             groupName = get_current_urlconf_params()['groupName']
107             # Check if we already loaded the current group in another
108             # middleware.
109             group = get_current_group()
110             if group is None or group.name != groupName:
111                 group = get_object_or_404(Group, name = groupName)
112         if 'groupName' in view_kwargs:
113             if view_kwargs.get( 'noGroup', False ):
114                 del view_kwargs['groupName']
115                 del view_kwargs['noGroup']
116             else:
117                 groupName = view_kwargs['groupName']
118                 if groupName == None: groupName = get_current_urlconf_params()['groupName']
119                 sphdata = get_current_sphdata()
120                 if group == None:
121                     group = get_object_or_404(Group, name = groupName )
122                     sphdata['group_fromhost'] = not get_sph_setting('community_groups_in_url')
123                 del view_kwargs['groupName']
124                 view_kwargs['group'] = group
125                 request.attributes['group'] = group
126                 #settings.TEMPLATE_DIRS = ( "/tmp/hehe", ) + settings.TEMPLATE_DIRS
127                 
128         set_current_group( group )
129         return None
130
131 # copied from http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser
132 # threadlocals middleware
133 try:
134     from threading import local
135 except ImportError:
136     from django.utils._threading_local import local
137
138 #print "Executing module body."
139 _thread_locals = local()
140 def get_current_request():
141     return getattr(_thread_locals, 'request', None)
142
143 def get_current_urlconf():
144     return getattr(get_current_request(), 'urlconf', None)
145
146 def get_current_session():
147     req = get_current_request()
148     if req == None: return None
149     return req.session
150
151 def get_current_user():
152     user = getattr(_thread_locals, 'user', None)
153     if user != None: return user
154     req = get_current_request()
155     if req == None: return None
156     return req.user
157
158 def get_current_group():
159     try:
160         return _thread_locals.group
161     except AttributeError, e:
162         logger.error('Unable to retrieve group. Is GroupMiddleware enabled?')
163         raise e
164
165 def get_current_urlconf_params():
166     return getattr(_thread_locals, 'urlconf_params', None)
167
168 def set_current_urlconf_params(urlconf_params):
169     _thread_locals.urlconf_params = urlconf_params
170
171 def set_current_group(group):
172     _thread_locals.group = group
173
174 def get_current_sphdata():
175     return getattr(_thread_locals, 'sphdata', None)
176    
177 class ThreadLocals(object):
178     """Middleware that gets various objects from the
179     request object and saves them in thread local storage."""
180     def process_request(self, request):
181         _thread_locals.request = request
182         _thread_locals.user = getattr(request, 'user', None)
183         _thread_locals.sphdata = { }
184         try:
185             delattr(_thread_locals, 'urlconf_params')
186         except AttributeError:
187             pass
188         _thread_locals.group = None
189        
190
191
192
193 ## copied from http://code.djangoproject.com/wiki/PageStatsMiddleware
194 import re
195 from operator import add
196 from time import time
197 from django.db import connection
198 import logging
199
200 logger = logging.getLogger('sphene.community.middleware')
201
202 class StatsMiddleware(object):
203
204     def process_view(self, request, view_func, view_args, view_kwargs):
205
206         # turn on debugging in db backend to capture time
207         from django.conf import settings
208         debug = settings.DEBUG
209         settings.DEBUG = True
210
211         # get number of db queries before we do anything
212         n = len(connection.queries)
213
214         # time the view
215         start = time()
216         response = None
217         try:
218             response = view_func(request, *view_args, **view_kwargs)
219         finally:
220             if request.path.startswith('/static'):
221                 return response
222
223             totTime = time() - start
224
225             # compute the db time for the queries just run
226             queries = len(connection.queries) - n
227             if queries:
228                 dbTime = reduce(add, [float(q['time'])
229                                       for q in connection.queries[n:]])
230             else:
231                 dbTime = 0.0
232
233             # and backout python time
234             pyTime = totTime - dbTime
235
236             # restore debugging setting
237             settings.DEBUG = debug
238
239             stats = {
240                 'totTime': totTime,
241                 'pyTime': pyTime,
242                 'dbTime': dbTime,
243                 'queries': queries,
244                 }
245
246             # replace the comment if found           
247             if response and response.content:
248                 s = response.content
249                 regexp = re.compile(r'(?P<cmt><!--\s*STATS:(?P<fmt>.*?)-->)')
250                 match = regexp.search(s)
251                 if match:
252                     s = s[:match.start('cmt')] + \
253                         match.group('fmt') % stats + \
254                         s[match.end('cmt'):]
255                     out = match.group('fmt') % stats
256                     #for query in connection.queries:
257                     #    logger.debug( '  %5s : %s' % (query['time'], query['sql'], ) )
258                     response.content = s
259
260             querystr = ''
261             for query in connection.queries:
262                 sql = query['sql']
263                 if sql is None: sql = " ?WTF?None?WTF? "
264                 querystr += "\t" + query['time'] + "\t" + sql + "\n"
265             logger.debug( 'All Queries: %s' % (querystr,) )
266             logger.info( 'Request %s: %s' % (request.get_full_path(), stats,) )
267
268         return response
269
270 from django.core.handlers.modpython import ModPythonRequest
271
272 class ModPythonSetLoggedinUser(object):
273     def process_request(self, request):
274         if not isinstance(request, ModPythonRequest):
275             return None
276
277         if not hasattr(request, '_req'):
278             return None
279
280         if not hasattr(request, 'user') or not request.user.is_authenticated():
281             return None
282
283         # request.user.username is a unicode string
284         # but _req.user requires an ascii string (afaik)
285         request._req.user = str(request.user.username)
286
287         return None
288
289
290 class PsycoMiddleware(object):
291     def process_request(self, request):
292         import psyco
293         psyco.profile()
294         return None
295
296 from sphene.community import PermissionDenied
297 from django.template.context import RequestContext
298 from django.shortcuts import render_to_response
299 from django.template import loader
300 from django.http import HttpResponseForbidden
301 class PermissionDeniedMiddleware(object):
302     def process_exception(self, request, exception):
303         if isinstance(exception, PermissionDenied):
304             return HttpResponseForbidden(loader.render_to_string( 'sphene/community/permissiondenied.html',
305                                                                   { 'exception': exception,
306                                                                     },
307                                                                   context_instance = RequestContext(request) ) )
308         return None
309
310
311
312 class LastModified(object):
313     """ Middleware that sets the Last-Modified and associated headers,
314     if requested by the view. (By setting the sph_lastmodified attribute
315     of the response object.
316
317     based on a contribution of Andrew Plotkin:
318     http://eblong.com/zarf/boodler/sitework/
319     """
320
321     def process_response(self, request, response):
322         stamp = getattr(response, 'sph_lastmodified', None)
323         if not stamp: return response
324
325         import rfc822
326         import calendar
327         if stamp is True:
328             val = rfc822.formatdate()
329         else:
330             val = rfc822.formatdate(calendar.timegm(stamp.timetuple()))
331         response['Last-Modified'] = val
332         response['Cache-Control'] = 'private, must-revalidate, max-age=0'
333         return response
334
Note: See TracBrowser for help on using the browser.