[three]Bean

Hacking tw2 resource injection (in pyramid)

Feb 11, 2012 | categories: python, toscawidgets, pyramid View Comments

In #toscawidgets this morning, zykes- was asking about how to do the jquery removal hack I wrote about a month back but in Pyramid instead of TurboGears2. First I'll summarize the problem, then show you our solution.

toscawidgets2 tw2.* provides lots of handy web ui widgets including a wrapper around jquery-ui, jqgrid, and lots of fancy data widgets. One of the problems it solves for you is de-duplicating resources. Say you're including two fancy jquery-related widgets. Both of them require that jquery.js be included on the page. tw2 includes a piece of middleware that tracks all the resources required by the widgets being rendered on a given request, reduces that list to a set with no duplicates, orders it by dependency, and injects it into the tag.

Usually this is fine, but in some cases you want an exception to the rule. Say, like in my previous post, you want to include jquery.js yourself manually and you'd rather not have tw2 stomping all over your javascript namespace. You could disable tw2 injection of all resources, but you want all the others included -- just not jquery.

There is no automatic detection and filtration flag implemented in tw2 and it would be tough to do in the general case. tw2 can't guarantee that it's own jquery.js and your jquery.js are the same, or different, or included, or not included, or anything -- it doesn't even try.

To get tw2 to not do what you don't want, you need to un-register tw2's jquery resource from the middleware yourself (on each request). Previously we came up with a working hack that does this in the context of a TurboGears2 app. Here's the same concept applied to a Pyramid app using a Pyramid "tween".

import tw2.core.core
import tw2.jquery

def remove_jq_factory(handler, registry):
    """ Remove tw2 jquery_js from tw2's middleware registry.

    In order to use this, you need to add the following to your
    myapp/__init__.py file:

        config.add_tween('myapp.tween.remove_jq_factory')

    """

    def remove_jq_tween(request):
        # Send the request on through to other tweens and to our app
        response = handler(request)

        # Before the response is modified by the tw2 middleware, let's remove
        # jquery_js from its registry.
        offending_links = [r.req().link for r in [
            tw2.jquery.jquery_js,
        ]]
        local = tw2.core.core.request_local()
        local['resources'] = [
            r for r in local.get('resources', list())
            if r.link not in offending_links
        ]

        return response

    return remove_jq_tween
View Comments
blog comments powered by Disqus