简体   繁体   中英

How to provide $ to third-party, external jQuery plugins in Django admin

I've included a couple of third-party jQuery plugins in my Django admin base template which assume "$" to be available.

For my own code, I've always been happy to just do

(function($) {
    my_code = 'here';
})(django.jQuery);

but how can I provide "$" to other people's code which sits in external files?

<script src="{{ STATIC_URL }}js/jquery.json-2.2.min.js" type="text/javascript"></script>

complains that "$" is undefined. I've tried to put

<script type="text/javascript">var $ = django.jQuery;</script>

before that external reference, but to no avail (btw, why is that? I understand loading happens concurrently, but execution? I can use that "$" immediately after defining it.).

I'm happy with the jQuery version that Django admin provides and really don't want to load another one. I also don't want to edit someone else's plugin so that it starts with the above "$" re-definition. EDIT: Neither do I want to wrap it like my own code, I just don't want to touch those files at all.

Do I really have to resort to putting $.getScript() - http://api.jquery.com/jQuery.getScript - into my anonymous function to load such files?

EDIT: After actually looking into that external file jquery.json-2.2.min.js, I saw it was already wrapped into a function that assumed "jQuery" to be available, rather than "$". After inserting

var jQuery = django.jQuery;

before the external reference, it worked fine. But is this really how this should be done?

Override django's staticfile admin/js/jquery.init.js by creating a file with the same name and path in your app's staticfiles directory.

The original content is this

/* Puts the included jQuery into our own namespace using noConflict and passing
 * it 'true'. This ensures that the included jQuery doesn't pollute the global
 * namespace (i.e. this preserves pre-existing values for both window.$ and
 * window.jQuery).
 */
var django = {
    "jQuery": jQuery.noConflict(true)
};

Just remove the .noConflict(true) .

For third party plugins, it's usually best to load your own copy of jQuery before including the other plugins. For Django 1.4+ this may look like so in your corresponding admin.py file:

class Media:
    js = (
        'http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
        '/static/js/third_party_plugin.js',
    )

If your plugins do not depend on a recent version of jQuery, you may also use Django's included version by defining $ and jQuery at the top of your plugin:

var jQuery = django.jQuery, $ = jQuery;

As of version 1.6, Django will ship with jQuery 1.9.1. Before that, jQuery 1.4 is used, which does not work for a lot of new/updated plugins.

Yeah, I remember this problem. I feel your pain.

A great workaround is to restructure your js files in such a way that Django can read them as URLs. In your URLs file, add the pattern below:

urlpatterns = patterns((r"^js(?:/(?P<type>\w+))?", "app.views.render_js"))

Now, in your init .py, add the following code:

JS_FILES = {"name" : "name.js",
            "thing" : "thing.js"};

def render_main_js(req, type = None) :
    return render_to_response(JS_FILES.get(type, "main.js"), mimetype="text/javascript");

Once the code is in place and assuming you have your javascript files in /js/* you can include your javascript by using the code below:

<script type="text/javascript" src="/js/name"></script>
<script type="text/javascript" src="/js/thing"></script>

There is a solution that works without double loading of jQuery, and without hacking jquery.init.js . It relies on the order the libraries are loaded in the admin.

Idea

  1. load jquery
  2. load third party libraries that depend on jQuery/$
  3. optional, load your own scripts, that use jQuery/$
  4. load jquery.init.js from Django (does the django.jQuery and noConflict thing)
  5. optional, load your own scripts, that use django.jQuery

Example

Media Attribute of an Admin, including select2.js.

    class Media:
        js = [
            'admin/js/vendor/jquery/jquery.js',
            'admin/js/vendor/select2/select2.full.js',
            'your_own/js/your_own-using-django.jQuery.js',            
            'admin/js/jquery.init.js',
            'your_own/js/your_own-using-django.jQuery.js',
        ]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM