Django-autocomplete-light: Django 2.0 widgets may load jQuery after dal

Created on 10 Jan 2018  路  13Comments  路  Source: yourlabs/django-autocomplete-light

In Django 2.0+, Django loads jquery.js instead of jquery.min.js when settings.DEBUG=True. See django/django@c19b56f which implements Django #28377 (docs).

In debug mode, when AdminDateWidget, the default admin widget for DateField, appears after a dal widget, select2.js can't find jQuery (Media.merge ordering breaks?) and we also get MediaOrderConflictWarning, as mentioned in #788.

As a temporary workaround, I've overridden AdminDateWidget to always load jquery.min.js, even in debug mode. I imagine the fix should go in Select2WidgetMixin, thoughts?

bug

Most helpful comment

I have a custom Autocomplete widget in a project that I use in all places in admin, so in my case, I was able to solve the issue with

from dal import autocomplete

class AutocompleteWidget(autocomplete.Select2)
        """Some custom code ..."""

        class Media:
            """Add jQuery dependency so autocomplete light's custom js
            is always inserted after jQuery
            """
            extra = '' if settings.DEBUG else '.min'
            js = [
                f'admin/js/vendor/jquery/jquery{extra}.js',  # new line
                # scripts from original app
                'autocomplete_light/jquery.init.js',
                'autocomplete_light/autocomplete.init.js',
                'autocomplete_light/vendor/select2/dist/js/select2.full.js',
                'autocomplete_light/select2.js',
                'admin/js/jquery.init.js',  # new line
            ]

All 13 comments

Interesting, is there any reason you're not using django 2.0 builtin autocomplete feature in the admin ?

Otherwise, I thought dal wouldn't load jquery at all, what's the output scripts like ?

dal is supposed to only load a file that should find the jquery instance to use

Do you think a fix is possible on dal's side ?

Interesting, is there any reason you're not using django 2.0 builtin autocomplete feature in the admin ?

I have two use cases, which if I'm understanding correctly, the built-in feature doesn't support:

  1. Filtering the autocomplete query based on forwarded form fields.
  2. Suggesting text (not ForeignKeys) in a CharField, also based on forwarded form fields.

Otherwise, I thought dal wouldn't load jquery at all, what's the output scripts like ?

Here is jQuery loaded by AdminDateWidget, when dal field appears before DateField:

<script type="text/javascript" src="/static/autocomplete_light/jquery.init.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/autocomplete.init.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/vendor/select2/dist/js/select2.full.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/vendor/select2/dist/js/i18n/en-US.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/select2.js"></script>
HERE <script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.js"></script>
<script type="text/javascript" src="/static/admin/js/jquery.init.js"></script>
[...]

If I remove jquery.js from AdminDateWidget Media, we get:

HERE <script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.js"></script>**
<script type="text/javascript" src="/static/autocomplete_light/jquery.init.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/autocomplete.init.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/vendor/select2/dist/js/select2.full.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/vendor/select2/dist/js/i18n/en-US.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/select2.js"></script>
<script type="text/javascript" src="/static/admin/js/jquery.init.js"></script>

So it looks like minification and debug mode is a red herring. The issue is AdminDateWidget adding jquery.js which Media.merge then orders after dal.

Do you think a fix is possible on dal's side ?

Not sure. We want to use Django's copy of jQuery, but get Django to order it first, right?

Hahah, seems like a lot of fun :D

Perhaps we should add an example app with this use case in the test project ?

How do you suggest we fix this ?

To fix this, I loaded the JQuery file two times by creating a new file template/admin/base.html in my django app, with as content:

{% extends "admin/base.html" %}

{% block extrahead %}
    <script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.js"></script>
{% endblock %}

My new file get loaded first and then the rest of the files get loaded.

<script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/jquery.init.js"></script>
script type="text/javascript" src="/static/autocomplete_light/autocomplete.init.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/vendor/select2/dist/js/select2.full.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/select2.js"></script>
<script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.js"></script>
<script type="text/javascript" src="/static/admin/js/jquery.init.js"></script>

It is quite a dirty solution, with which I am not satisfied but at least it solved my issue for the short term with minimal effort.

Thanks for your feedback! I wonder why I can't reproduce this in the test project, any idea ?

I am not sure but I believe @daradib pinpointed the cause to be with the AdminDateWidget of Django 2.0. I also had the error in an Admin form where a date widget was present.

Affected by this issue also, wrote a ticket in Django Tickets
https://code.djangoproject.com/ticket/29264

Will use @maxcmoi89 solution for now

I have a custom Autocomplete widget in a project that I use in all places in admin, so in my case, I was able to solve the issue with

from dal import autocomplete

class AutocompleteWidget(autocomplete.Select2)
        """Some custom code ..."""

        class Media:
            """Add jQuery dependency so autocomplete light's custom js
            is always inserted after jQuery
            """
            extra = '' if settings.DEBUG else '.min'
            js = [
                f'admin/js/vendor/jquery/jquery{extra}.js',  # new line
                # scripts from original app
                'autocomplete_light/jquery.init.js',
                'autocomplete_light/autocomplete.init.js',
                'autocomplete_light/vendor/select2/dist/js/select2.full.js',
                'autocomplete_light/select2.js',
                'admin/js/jquery.init.js',  # new line
            ]

Thanks for the quick hack @ron8mcr, please make a pull request if it works for you so we can try it in an RC.

Also, anybody to just use the same jquery and select2 paths as the admin, i mean from django/contrib/admin/static/admin rather than from dal's repo itself ? In this case, dal would only rely on the admin's static and we could drop the git submodule which vendorizes select2 ?

This seems to be the last release blocker for 3.3.0 :joy:

See also https://github.com/django/django/pull/9743, where I've tried to fix this by keeping the admin's media separate from the form's when merging them.

Could you please try #1002 see if that works for you ?

Should be fixed in 35b0046 on master

@jpic
Thanks for addressing this!

Was this page helpful?
0 / 5 - 0 ratings