Login

Template tags to integrate with modconcat

Author:
matthanger
Posted:
July 21, 2009
Language:
Python
Version:
1.0
Score:
0 (after 0 ratings)

Assumes mod_concat is installed: http://code.google.com/p/modconcat/

Django template tags that combine blocks of CSS and Javascript into modconcat friendly URLs. Takes this:

{% cssconcat "{{ MEDIA_URL }}css/" %} <link href="{{ MEDIA_URL }}css/a.css" rel="stylesheet" type="text/css" /> <link href="{{ MEDIA_URL }}css/b.css" rel="stylesheet" type="text/css" /> <link href="{{ MEDIA_URL }}css/c.css" rel="stylesheet" type="text/css" /> {% endcssconcat %}

And outputs this:

<link href="/site_media/??a.css,b.css,c.css" rel="stylesheet" type="text/css" />

Similarly for javascript:

{% jsconcat "{{ MEDIA_URL }}js/" %} <script src="{{ MEDIA_URL }}js/a.js" type="text/javascript"></script> <script src="{{ MEDIA_URL }}js/b.js" type="text/javascript"></script> <script src="{{ MEDIA_URL }}js/c.js" type="text/javascript"></script> {% endjsconcat %}

becomes:

<script src="/site_media/??a.js,b.js,c.js" type="text/javascript"></script>

 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
"""
Django template tags to enable the use of the modconcat Apache module. Set ENABLE_CONCAT=True in settings.py to enable.

http://code.google.com/p/modconcat
"""

import re
HREF_PATTERN = re.compile('href="([^"]*)"')
SRC_PATTERN = re.compile('src="([^"]*)"')

from django import template
from django.template import Template
register = template.Library()

from django.conf import settings

def _concat_enabled():
    """ Tests if concatenation is enabled in the settings file. """
    return hasattr(settings, 'ENABLE_CONCAT') and settings.ENABLE_CONCAT

@register.tag
def cssconcat(parser, token):
    """
    Takes a block of one or more <link> elements, concatenates all of the href's together
    into a single href suitable for modconcat. Example:
    
    <link href="/site_media/a.css" rel="stylesheet" type="text/css" /> 
    <link href="/site_media/b.css" rel="stylesheet" type="text/css" /> 
    <link href="/site_media/c.css" rel="stylesheet" type="text/css" /> 
    
    ...becomes...
    
    <link href="/site_media/??a.css,b.css,c.css" rel="stylesheet" type="text/css" />     
    """
    tag_name, basepath = token.split_contents()
    nodelist = parser.parse(('endcssconcat',))
    parser.delete_first_token()
    
    return ConcatCssNode(nodelist, basepath[1:-1]) #strip quotes

@register.tag
def jsconcat(parser, token):
    """
    Takes a block of one or more <script> elements, concatenates all of the src's together
    into a single src suitable for modconcat. Example:

    <script src="/site_media/a.js" type="text/javascript"></script> 
    <script src="/site_media/b.js" type="text/javascript"></script> 
    <script src="/site_media/c.js" type="text/javascript"></script> 

    ...becomes...
    
    <script src="/site_media/??a.js,b.js,c.js" type="text/javascript"></script> 
    """
    tag_name, basepath = token.split_contents()
    nodelist = parser.parse(('endjsconcat',))
    parser.delete_first_token()
    
    return ConcatJavascriptNode(nodelist, basepath[1:-1]) #strip quotes

class ConcatCssNode(template.Node):
    """ Renders the cssconcat template tag """
    def __init__(self, nodelist, basepath):
        self.nodelist = nodelist
        self.basepath = basepath
        
    def render(self, context):
        """ Renders the cssconcat template tag """
        if _concat_enabled():
            output = self.nodelist.render(context)
            basepath = Template(self.basepath).render(context)
            css_paths = HREF_PATTERN.findall(output)
            return u'<link href="%s??%s" rel="stylesheet" type="text/css" />' % \
                (basepath, ','.join(css_paths).replace(basepath, ''))

        return self.nodelist.render(context)

class ConcatJavascriptNode(template.Node):
    """ Renders the jsconcat template tag """
    def __init__(self, nodelist, basepath):
        self.nodelist = nodelist
        self.basepath = basepath

    def render(self, context):
        """ Renders the jsconcat template tag """        
        if _concat_enabled():
            output = self.nodelist.render(context)   
            basepath = Template(self.basepath).render(context)     
            javascript_paths = SRC_PATTERN.findall(output)
            return u'<script src="%s??%s" type="text/javascript"></script> ' % \
                (basepath, ','.join(javascript_paths).replace(basepath, ''))

        return self.nodelist.render(context)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 3 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

Please login first before commenting.