def copy_dir(self, source, dest, level=0): '''Copies the static files from one directory to another. If this command is run, we assume the user wants to overwrite any existing files.''' # ensure the destination exists if not os.path.exists(dest): os.mkdir(dest) # go through the files in this directory for fname in os.listdir(source): source_path = os.path.join(source, fname) dest_path = os.path.join(dest, fname) ext = os.path.splitext(fname)[1].lower() ### EXPLICIT IGNORE ### if self.ignore_file(fname): pass ### DIRECTORIES ### # ignore these directories elif os.path.isdir(source_path) and fname in ( 'templates', 'views', get_setting('TEMPLATES_CACHE_DIR'), '__pycache__' ): pass # if a directory, create it in the destination and recurse elif os.path.isdir(source_path): if not os.path.exists(dest_path): os.mkdir(dest_path) elif not os.path.isdir(dest_path): # could be a file or link os.unlink(dest_path) os.mkdir(dest_path) self.copy_dir(source_path, dest_path, level+1) ### FILES ### # we don't do any regular files at the top level elif level == 0: pass # ignore these files elif fname in ( '__init__.py', ): pass # ignore these extensions elif ext in ( '.cssm', '.jsm' ): pass # if a regular Javscript file, minify it elif ext == '.js' and get_setting('MINIFY_JS_CSS', False) and JSMIN: fin = open(source_path) fout = open(dest_path, 'w') fout.write(jsmin(fin.read())) fout.close() fin.close() elif ext == '.css' and get_setting('MINIFY_JS_CSS', False) and CSSMIN: fin = open(source_path) fout = open(dest_path, 'w') fout.write(cssmin(fin.read())) fout.close() fin.close() # if we get here, it's a binary file like an image, movie, pdf, etc. else: shutil.copy2(source_path, dest_path)
def __init__(self, template, cgi_id=None): # set up the directories so we can go through them fast on render self.template_dir, self.template_name = os.path.split(os.path.splitext(template.filename)[0]) self.app_dir = os.path.dirname(self.template_dir) self.app = os.path.split(self.app_dir)[1] # ensure we have renderers for this template if self.app not in SCRIPT_RENDERERS: SCRIPT_RENDERERS[self.app] = MakoTemplateRenderer(self.app, 'scripts') if self.app not in STYLE_RENDERERS: STYLE_RENDERERS[self.app] = MakoTemplateRenderer(self.app, 'styles') # the static templatename.scss file try: scss_file = os.path.join(self.app_dir, 'styles', self.template_name + '.scss') scss_stat = os.stat(scss_file) try: css_file = os.path.join(self.app_dir, 'styles', self.template_name + '.css') css_stat = os.stat(css_file) # update the CSS file if the SCCS file is newer if scss_stat.st_mtime > css_stat.st_mtime: os.system(get_setting('SCCS_BINARY', '/usr/bin/env scss') + ' %s %s %s' % (get_setting('SCCS_ARGS', ''), scss_file, css_file)) except OSError: # if no CSS file exists, create one os.system(get_setting('SCCS_BINARY', '/usr/bin/env scss') + ' %s %s %s' % (get_setting('SCCS_ARGS', ''), scss_file, css_file)) except OSError: # no SCCS file exists .. continue as normal pass # the static templatename.css file try: fstat = os.stat(os.path.join(self.app_dir, 'styles', self.template_name + '.css')) self.css = '<link rel="stylesheet" type="text/css" href="%s?%s" />' % (os.path.join(settings.STATIC_URL, self.app, 'styles', self.template_name + '.css'), cgi_id if cgi_id != None else int(fstat.st_mtime)) except OSError: self.css = None # the mako-rendered templatename.cssm file try: fstat = os.stat(os.path.join(self.app_dir, 'styles', self.template_name + '.cssm')) self.cssm = self.template_name + '.cssm' except OSError: self.cssm = None # the static templatename.js file try: fstat = os.stat(os.path.join(self.app_dir, 'scripts', self.template_name + '.js')) self.js = '<script src="%s?%s"></script>' % (os.path.join(settings.STATIC_URL, self.app, 'scripts', self.template_name + '.js'), cgi_id if cgi_id != None else int(fstat.st_mtime)) except OSError: self.js = None # the mako-rendered templatename.jsm file try: fstat = os.stat(os.path.join(self.app_dir, 'scripts', self.template_name + '.jsm')) self.jsm = self.template_name + '.jsm' except OSError: self.jsm = None
def __init__(self, app_path, template_subdir='templates'): '''Creates a renderer to the given path (relateive to the project root where settings.STATIC_ROOT points to)''' project_path = os.path.normpath(settings.BASE_DIR) self.app_path = app_path template_dir = get_app_template_dir(app_path, template_subdir) # raises ImproperlyConfigured if error self.template_search_dirs = [ template_dir ] if get_setting('TEMPLATES_DIRS', False): self.template_search_dirs.extend(get_setting('TEMPLATES_DIRS')) self.template_search_dirs.append(settings.BASE_DIR) self.cache_root = os.path.abspath(os.path.join(project_path, app_path, get_setting('TEMPLATES_CACHE_DIR'), template_subdir)) self.tlookup = TemplateLookup(directories=self.template_search_dirs, imports=get_setting('DEFAULT_TEMPLATE_IMPORTS'), module_directory=self.cache_root, collection_size=2000, filesystem_checks=settings.DEBUG, input_encoding=get_setting('DEFAULT_TEMPLATE_ENCODING', 'utf-8')) # Use the default django engine (to get the list of context processors) self.engine = Engine.get_default()
def get_template_js(self, request, context): '''Retrieves the static and mako_rendered CSS''' ret = [] for template in self.template_chain: ti = getattr(template, DMP_ATTR_NAME) if ti.js: ret.append(ti.js) # the <script> was already created once in the constructor if ti.jsm: js_text = SCRIPT_RENDERERS[ti.app].render(request, ti.jsm, context.kwargs) if JSMIN and get_setting('MINIFY_JS_CSS', False): js_text = jsmin(js_text) ret.append('<script>%s</script>' % js_text) return '\n'.join(ret)
def get_template_css(self, request, context): '''Retrives the static and mako-rendered CSS''' ret = [] for template in reversed(self.template_chain): # reverse so lower CSS overrides higher CSS in the inheritance chain ti = getattr(template, DMP_ATTR_NAME) if ti.css: ret.append(ti.css) # the <link> was already created once in the constructor if ti.cssm: css_text = STYLE_RENDERERS[ti.app].render(request, ti.cssm, context.kwargs) if JSMIN and get_setting('MINIFY_JS_CSS', False): css_text = cssmin(css_text) ret.append('<style type="text/css">%s</style>' % css_text) return '\n'.join(ret)
def get_template_js(self, request, context): '''Retrieves the static and mako_rendered CSS''' ret = [] for template in self.template_chain: ti = getattr(template, DMP_ATTR_NAME) if ti.js: ret.append( ti.js ) # the <script> was already created once in the constructor if ti.jsm: js_text = SCRIPT_RENDERERS[ti.app].render( request, ti.jsm, context.kwargs) if JSMIN and get_setting('MINIFY_JS_CSS', False): js_text = jsmin(js_text) ret.append('<script>%s</script>' % js_text) return '\n'.join(ret)
def get_template_css(self, request, context): '''Retrives the static and mako-rendered CSS''' ret = [] for template in reversed( self.template_chain ): # reverse so lower CSS overrides higher CSS in the inheritance chain ti = getattr(template, DMP_ATTR_NAME) if ti.css: ret.append( ti.css ) # the <link> was already created once in the constructor if ti.cssm: css_text = STYLE_RENDERERS[ti.app].render( request, ti.cssm, context.kwargs) if JSMIN and get_setting('MINIFY_JS_CSS', False): css_text = cssmin(css_text) ret.append('<style type="text/css">%s</style>' % css_text) return '\n'.join(ret)
def render_to_response(self, request, template, params={}, def_name=None): '''Runs a template and returns an HttpRequest object to it. This method returns a django.http.Http404 exception if the template is not found. If the template raises a django_mako_plus.controller.RedirectException, the browser is redirected to the given page, and a new request from the browser restarts the entire DMP routing process. If the template raises a django_mako_plus.controller.InternalRedirectException, the entire DMP routing process is restarted internally (the browser doesn't see the redirect). The method throws two signals: 1. dmp_signal_pre_render_template: you can (optionally) return a new Mako Template object from a receiver to replace the normal template object that is used for the render operation. 2. dmp_signal_post_render_template: you can (optionally) return a string to replace the string from the normal template object render. @request The request context from Django. If this is None, any TEMPLATE_CONTEXT_PROCESSORS defined in your settings file will be ignored but the template will otherwise render fine. @template The template file path to render. This is relative to the app_path/controller_TEMPLATES_DIR/ directory. For example, to render app_path/templates/page1, set template="page1.html", assuming you have set up the variables as described in the documentation above. @params A dictionary of name=value variables to send to the template page. @def_name Limits output to a specific top-level Mako <%block> or <%def> section within the template. If the section is a <%def>, it must have no parameters. For example, def_name="foo" will call <%block name="foo"></%block> or <%def name="foo()"></def> within the template. ''' try: content_type = mimetypes.types_map.get(os.path.splitext(template)[1].lower(), 'text/html') content = self.render(request, template, params, def_name) return HttpResponse(content.encode(settings.DEFAULT_CHARSET), content_type='%s; charset=%s' % (content_type, settings.DEFAULT_CHARSET)) except TopLevelLookupException: # template file not found log.debug('DMP :: template "%s" not found in search path: %s.' % (template, self.template_search_dirs)) raise Http404() except RedirectException: # redirect to another page e = sys.exc_info()[1] # Py2.7 and Py3+ compliant log.debug('DMP :: view function %s.%s redirected processing to %s' % (request.dmp_router_module, request.dmp_router_function, e.redirect_to)) # send the signal if get_setting('SIGNALS', False): signals.dmp_signal_redirect_exception.send(sender=sys.modules[__name__], request=request, exc=e) # send the browser the redirect command return e.get_response(request)
def route_request(request): '''The main router for all calls coming in to the system.''' # output the variables so the programmer can debug where this is routing log.debug('DMP :: processing: app=%s, page=%s, func=%s, urlparams=%s' % (request.dmp_router_app, request.dmp_router_page, request.dmp_router_function, request.urlparams)) # set the full function location request.dmp_router_module = '.'.join([ request.dmp_router_app, 'views', request.dmp_router_page ]) # first try going to the view function for this request # we look for a views/name.py file where name is the same name as the HTML file response = None while True: # enables the InternalRedirectExceptions to loop around full_module_filename = os.path.normpath(os.path.join(settings.BASE_DIR, request.dmp_router_module.replace('.', '/') + '.py')) try: # look for the module, and if not found go straight to template if not os.path.exists(full_module_filename): log.debug('DMP :: module %s not found; sending processing directly to template %s.html' % (request.dmp_router_module, request.dmp_router_page_full)) try: dmp_renderer = get_renderer(request.dmp_router_app) except ImproperlyConfigured as e: log.debug('DMP :: %s' % (e)) raise Http404 return dmp_renderer.render_to_response(request, '%s.html' % request.dmp_router_page_full) # find the function module_obj = import_module(request.dmp_router_module) if not hasattr(module_obj, request.dmp_router_function): log.debug('DMP :: view function/class %s not in module %s; returning 404 not found.' % (request.dmp_router_function, request.dmp_router_module)) raise Http404 func_obj = getattr(module_obj, request.dmp_router_function) # see if the func_obj is actually a class -- we might be doing class-based views here if isinstance(func_obj, type): request.dmp_router_class = request.dmp_router_function request.dmp_router_function = request.method.lower() if not hasattr(func_obj, request.dmp_router_function): log.debug('DMP :: view class %s.%s has no method named %s; returning 404 not found.' % (request.dmp_router_module, request.dmp_router_class, request.dmp_router_function)) raise Http404 func_obj = getattr(func_obj(), request.dmp_router_function) # move to the class.get(), class.post(), etc. method # ensure it is decorated with @view_function - this is for security so only certain functions can be called if getattr(func_obj, 'dmp_view_function', False) != True: log.debug('DMP :: view function/class %s found successfully, but it is not decorated with @view_function; returning 404 not found. Note that if you have multiple decorators on a function, the @view_function decorator must be listed first.' % (request.dmp_router_function)) raise Http404 # send the pre-signal if get_setting('SIGNALS', False): for receiver, ret_response in signals.dmp_signal_pre_process_request.send(sender=sys.modules[__name__], request=request): if isinstance(ret_response, (HttpResponse, StreamingHttpResponse)): return ret_response # call view function if request.dmp_router_class == None: log.debug('DMP :: calling view function %s.%s' % (request.dmp_router_module, request.dmp_router_function)) else: log.debug('DMP :: calling class-based view function %s.%s.%s' % (request.dmp_router_module, request.dmp_router_class, request.dmp_router_function)) response = func_obj(request) # send the post-signal if get_setting('SIGNALS', False): for receiver, ret_response in signals.dmp_signal_post_process_request.send(sender=sys.modules[__name__], request=request, response=response): if ret_response != None: response = ret_response # sets it to the last non-None in the signal receiver chain # if we didn't get a correct response back, send a 404 if not isinstance(response, (HttpResponse, StreamingHttpResponse)): if request.dmp_router_class == None: log.debug('DMP :: view function %s.%s failed to return an HttpResponse (or the post-signal overwrote it). Returning Http404.' % (request.dmp_router_module, request.dmp_router_function)) else: log.debug('DMP :: class-based view function %s.%s.%s failed to return an HttpResponse (or the post-signal overwrote it). Returning Http404.' % (request.dmp_router_module, request.dmp_router_class, request.dmp_router_function)) raise Http404 # return the response return response except InternalRedirectException: ivr = sys.exc_info()[1] # Py2.7 and Py3+ compliant # send the signal if get_setting('SIGNALS', False): signals.dmp_signal_internal_redirect_exception.send(sender=sys.modules[__name__], request=request, exc=ivr) # do the internal redirect request.dmp_router_module = ivr.redirect_module request.dmp_router_function = ivr.redirect_function full_module_filename = os.path.normpath(os.path.join(settings.BASE_DIR, request.dmp_router_module.replace('.', '/') + '.py')) log.debug('DMP :: received an InternalViewRedirect to %s -> %s' % (full_module_filename, request.dmp_router_function)) except RedirectException: # redirect to another page e = sys.exc_info()[1] # Py2.7 and Py3+ compliant if request.dmp_router_class == None: log.debug('DMP :: view function %s.%s redirected processing to %s' % (request.dmp_router_module, request.dmp_router_function, e.redirect_to)) else: log.debug('DMP :: class-based view function %s.%s.%s redirected processing to %s' % (request.dmp_router_module, request.dmp_router_class, request.dmp_router_function, e.redirect_to)) # send the signal if get_setting('SIGNALS', False): signals.dmp_signal_redirect_exception.send(sender=sys.modules[__name__], request=request, exc=e) # send the browser the redirect command return e.get_response(request) # the code should never get here raise Exception("Django-Mako-Plus router error: The route_request() function should not have been able to get to this point. Please notify the owner of the DMP project. Thanks.")
from django.core.management.base import BaseCommand, CommandError from django.utils.importlib import import_module from django.conf import settings from django_mako_plus.controller import router, get_setting from optparse import make_option import os, os.path, shutil, fnmatch # import minification if requested if get_setting('MINIFY_JS_CSS', False): try: from rjsmin import jsmin JSMIN = True except ImportError: JSMIN = False try: from rcssmin import cssmin CSSMIN = True except ImportError: CSSMIN = False class Command(BaseCommand): args = '' help = 'Collects static files, such as media, scripts, and styles, to a common directory root. This is done to prepare for deployment.' can_import_settings = True option_list = BaseCommand.option_list + ( make_option( '--overwrite', action='store_true', dest='overwrite', default=False,
def copy_dir(self, source, dest, level=0): '''Copies the static files from one directory to another. If this command is run, we assume the user wants to overwrite any existing files.''' # ensure the destination exists if not os.path.exists(dest): os.mkdir(dest) # go through the files in this directory for fname in os.listdir(source): source_path = os.path.join(source, fname) dest_path = os.path.join(dest, fname) ext = os.path.splitext(fname)[1].lower() ### EXPLICIT IGNORE ### if self.ignore_file(fname): pass ### DIRECTORIES ### # ignore these directories elif os.path.isdir(source_path) and fname in ( 'templates', 'views', get_setting('TEMPLATES_CACHE_DIR'), '__pycache__'): pass # if a directory, create it in the destination and recurse elif os.path.isdir(source_path): if not os.path.exists(dest_path): os.mkdir(dest_path) elif not os.path.isdir(dest_path): # could be a file or link os.unlink(dest_path) os.mkdir(dest_path) self.copy_dir(source_path, dest_path, level + 1) ### FILES ### # we don't do any regular files at the top level elif level == 0: pass # ignore these files elif fname in ('__init__.py', ): pass # ignore these extensions elif ext in ('.cssm', '.jsm'): pass # if a regular Javscript file, minify it elif ext == '.js' and get_setting('MINIFY_JS_CSS', False) and JSMIN: fin = open(source_path) fout = open(dest_path, 'w') fout.write(jsmin(fin.read())) fout.close() fin.close() elif ext == '.css' and get_setting('MINIFY_JS_CSS', False) and CSSMIN: fin = open(source_path) fout = open(dest_path, 'w') fout.write(cssmin(fin.read())) fout.close() fin.close() # if we get here, it's a binary file like an image, movie, pdf, etc. else: shutil.copy2(source_path, dest_path)
def render(self, request, template, params={}, def_name=None): '''Runs a template and returns a string. Normally, you probably want to call render_to_response instead because it gives a full HttpResponse or Http404. This method raises a mako.exceptions.TopLevelLookupException if the template is not found. The method throws two signals: 1. dmp_signal_pre_render_template: you can (optionally) return a new Mako Template object from a receiver to replace the normal template object that is used for the render operation. 2. dmp_signal_post_render_template: you can (optionally) return a string to replace the string from the normal template object render. @request The request context from Django. If this is None, 1) any TEMPLATE_CONTEXT_PROCESSORS defined in your settings file will be ignored and 2) DMP signals will not be sent, but the template will otherwise render fine. @template The template file path to render. This is relative to the app_path/controller_TEMPLATES_DIR/ directory. For example, to render app_path/templates/page1, set template="page1.html", assuming you have set up the variables as described in the documentation above. @params A dictionary of name=value variables to send to the template page. @def_name Limits output to a specific top-level Mako <%block> or <%def> section within the template. If the section is a <%def>, it must have no parameters. For example, def_name="foo" will call <%block name="foo"></%block> or <%def name="foo()"></def> within the template. The block/def must be defined in the exact template. DMP does not support calling defs from super-templates. ''' # must convert the request context to a real dict to use the ** below context_dict = {} context_dict['request'] = request context_dict['settings'] = settings try: context_dict['STATIC_URL'] = settings.STATIC_URL # this is used so much in templates, it's useful to have it always available except AttributeError: pass context = Context(params) if request == None else RequestContext(request, params) # Django's RequestContext automatically runs all the TEMPLATE_CONTEXT_PROCESSORS and populates with variables with context.bind_template(self): for d in context: context_dict.update(d) # get the template template_obj = self.get_template(template) # send the pre-render signal if get_setting('SIGNALS', False) and request != None: for receiver, ret_template_obj in signals.dmp_signal_pre_render_template.send(sender=self, request=request, context=context, template=template_obj): if ret_template_obj != None: # changes the template object to the received template_obj = ret_template_obj # do we need to limit down to a specific def? # this only finds within the exact template (won't go up the inheritance tree) # I wish I could make it do so, but can't figure this out render_obj = template_obj if def_name: # do we need to limit to just a def? render_obj = template_obj.get_def(def_name) # PRIMARY FUNCTION: render the template log.debug('DMP :: rendering template %s' % template_obj.filename) if settings.DEBUG: try: content = render_obj.render_unicode(**context_dict) except: content = html_error_template().render_unicode() else: # this is outside the above "try" loop because in non-DEBUG mode, we want to let the exception throw out of here (without having to re-raise it) content = render_obj.render_unicode(**context_dict) # send the post-render signal if get_setting('SIGNALS', False) and request != None: for receiver, ret_content in signals.dmp_signal_post_render_template.send(sender=self, request=request, context=context, template=template_obj, content=content): if ret_content != None: content = ret_content # sets it to the last non-None return in the signal receiver chain # return return content
def __init__(self, template, cgi_id=None): # set up the directories so we can go through them fast on render self.template_dir, self.template_name = os.path.split( os.path.splitext(template.filename)[0]) self.app_dir = os.path.dirname(self.template_dir) self.app = os.path.split(self.app_dir)[1] # ensure we have renderers for this template if self.app not in SCRIPT_RENDERERS: SCRIPT_RENDERERS[self.app] = MakoTemplateRenderer( self.app, 'scripts') if self.app not in STYLE_RENDERERS: STYLE_RENDERERS[self.app] = MakoTemplateRenderer( self.app, 'styles') # the static templatename.scss file try: scss_file = os.path.join(self.app_dir, 'styles', self.template_name + '.scss') scss_stat = os.stat(scss_file) try: css_file = os.path.join(self.app_dir, 'styles', self.template_name + '.css') css_stat = os.stat(css_file) # update the CSS file if the SCCS file is newer if scss_stat.st_mtime > css_stat.st_mtime: os.system( get_setting('SCCS_BINARY', '/usr/bin/env scss') + ' %s %s %s' % (get_setting('SCCS_ARGS', ''), scss_file, css_file)) except OSError: # if no CSS file exists, create one os.system( get_setting('SCCS_BINARY', '/usr/bin/env scss') + ' %s %s %s' % (get_setting('SCCS_ARGS', ''), scss_file, css_file)) except OSError: # no SCCS file exists .. continue as normal pass # the static templatename.css file try: fstat = os.stat( os.path.join(self.app_dir, 'styles', self.template_name + '.css')) self.css = '<link rel="stylesheet" type="text/css" href="%s?%s" />' % ( os.path.join(settings.STATIC_URL, self.app, 'styles', self.template_name + '.css'), cgi_id if cgi_id != None else int(fstat.st_mtime)) except OSError: self.css = None # the mako-rendered templatename.cssm file try: fstat = os.stat( os.path.join(self.app_dir, 'styles', self.template_name + '.cssm')) self.cssm = self.template_name + '.cssm' except OSError: self.cssm = None # the static templatename.js file try: fstat = os.stat( os.path.join(self.app_dir, 'scripts', self.template_name + '.js')) self.js = '<script src="%s?%s"></script>' % (os.path.join( settings.STATIC_URL, self.app, 'scripts', self.template_name + '.js'), cgi_id if cgi_id != None else int(fstat.st_mtime)) except OSError: self.js = None # the mako-rendered templatename.jsm file try: fstat = os.stat( os.path.join(self.app_dir, 'scripts', self.template_name + '.jsm')) self.jsm = self.template_name + '.jsm' except OSError: self.jsm = None
objects in a dict or other type of cache. This isn't done here to keep things simpler. ''' from django.conf import settings from django_mako_plus.controller.router import MakoTemplateRenderer from django_mako_plus.controller import get_setting import os, os.path, time DMP_ATTR_NAME = 'dmp_templateinfo' # used to attach TemplateInfo objects to Mako templates # Import minification if requested JSMIN = False CSSMIN = False if get_setting('MINIFY_JS_CSS', False) and not settings.DEBUG: try: from rjsmin import jsmin JSMIN = True except ImportError: pass try: from rcssmin import cssmin CSSMIN = True except ImportError: pass ####################################################################### ### A dict of template renderers for scripts and styles in our apps. ### These are created as needed in TemplateInfo below and cached here.
def process_request(self, request): '''Called for each browser request. This adds the following fields to the request object: request.dmp_router_app The Django application (such as "calculator"). request.dmp_router_page The view module (such as "calc" for calc.py). request.dmp_router_page_full The view module as specified in the URL, including the function name if specified. request.dmp_router_function The function within the view module to be called (usually "process_request"). request.dmp_router_module The module path in Python terms, such as calculator.views.calc. request.urlparams A list of the remaining url parts (see the calc.py example). This method is run as part of the middleware processing, so it runs long before the route_request() method at the top of this file. ''' # split the path path_parts = request.path[1:].split('/') # [1:] to remove the leading / # splice the list if the settings need it start_index = get_setting('URL_START_INDEX', 0) if start_index > 0: path_parts = path_parts[start_index:] # ensure that we have at least 2 path_parts to work with # by adding the default app and/or page as needed if len(path_parts) == 0: path_parts.append(get_setting('DEFAULT_APP', 'homepage')) path_parts.append(get_setting('DEFAULT_PAGE', 'index')) elif len(path_parts) == 1: # /app or /page if path_parts[0] in TEMPLATE_RENDERERS: # one of our apps specified, so insert the default page path_parts.append(get_setting('DEFAULT_PAGE', 'index')) else: # not one of our apps, so insert the app and assume path_parts[0] is a page in that app path_parts.insert(0, get_setting('DEFAULT_APP', 'homepage')) if not path_parts[1]: # was the page empty? path_parts[1] = get_setting('DEFAULT_PAGE', 'index') else: # at this point in the elif, we know len(path_parts) >= 2 if path_parts[0] not in TEMPLATE_RENDERERS: # the first part was not one of our apps, so insert the default app path_parts.insert(0, get_setting('DEFAULT_APP', 'homepage')) if not path_parts[1]: # is the page empty? path_parts[1] = get_setting('DEFAULT_PAGE', 'index') # set the app and page in the request request.dmp_router_app = path_parts[0] request.dmp_router_page = path_parts[1] request.dmp_router_page_full = path_parts[1] # might be different from dmp_router_page when split by '.' below # see if a function is specified with the page (the . separates a function name) du_pos = request.dmp_router_page.find('.') if du_pos >= 0: request.dmp_router_function = request.dmp_router_page[du_pos+1:] request.dmp_router_function = request.dmp_router_function.replace('.', '_') # python methods can't have dot, so replace with an underscore if in the name request.dmp_router_page = request.dmp_router_page[:du_pos] else: # the . not found, and the __ not found, so go to default function name request.dmp_router_function = 'process_request' # set the class to be None (it is set later if we find a class-based view) request.dmp_router_class = None # set up the urlparams with the reamining path parts # note that I'm not using unquote_plus because the + switches to a space *after* the question mark (in the regular parameters) # in the normal url, spaces have to be quoted with %20. Thanks Rosie for the tip. request.urlparams = URLParamList([ unquote(s) for s in path_parts[2:] ])
Note that with this Django starter kit, we recreate the static renderer each time. At deployment, it would speed things up considerably to cache these StaticRenderer objects in a dict or other type of cache. This isn't done here to keep things simpler. ''' from django.conf import settings from django_mako_plus.controller.router import MakoTemplateRenderer from django_mako_plus.controller import get_setting import os, os.path, time DMP_ATTR_NAME = 'dmp_templateinfo' # used to attach TemplateInfo objects to Mako templates # Import minification if requested JSMIN = False CSSMIN = False if get_setting('MINIFY_JS_CSS', False) and not settings.DEBUG: try: from rjsmin import jsmin JSMIN = True except ImportError: pass try: from rcssmin import cssmin CSSMIN = True except ImportError: pass ####################################################################### ### A dict of template renderers for scripts and styles in our apps. ### These are created as needed in TemplateInfo below and cached here. ### One for each app is created in each dict.