django-autocomplete-light: The jQuery inits are not loaded in the correct order in 3.5.1
There’s a lot going on below, but the heart of the problem is that in 3.5.0, /static/admin/js/jquery.init.js
is loaded before /static/autocomplete_light/jquery.init.js
(which works) and in 3.5.1 it’s the opposite (which fails). Making that one change alone (building with 3.5.0 as the basis) is enough to trigger this failure.
Given Django 3.0.3 with:
INSTALLED_APPS = [
'corsheaders',
'dal',
'dal_select2',
'django.contrib.admin',
'django.contrib.auth',
.....
In 3.5.0, django-autocomplete-light works fine, but in 3.5.1 it doesn’t.
The main console error is Select2: An instance of jQuery or a jQuery-compatible library was not found. Make sure that you are including jQuery before Select2 on your web page.
followed by jQuery.Deferred exception: $(...).select2 is not a function TypeError: $(...).select2 is not a function
However, we do load it - but the load order is slightly different between 3.5.0 and 3.5.1. Here’s the header of the admin page in question:
Built with 3.5.0:
<!DOCTYPE html>
<html lang="en-us" >
<head>
<title>Add Organization settings | Django site admin</title>
<link rel="stylesheet" type="text/css" href="/static/admin/css/base.css">
<link rel="stylesheet" type="text/css" href="/static/admin/css/forms.css">
<script type="text/javascript" src="/admin/jsi18n/"></script>
<link href="/static/vendor/select2/dist/css/select2.css" type="text/css" media="screen" rel="stylesheet">
<link href="/static/admin/css/autocomplete.css" type="text/css" media="screen" rel="stylesheet">
<link href="/static/autocomplete_light/select2.css" type="text/css" media="screen" rel="stylesheet">
<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>
<script type="text/javascript" src="/static/autocomplete_light/jquery.init.js"></script>
<script type="text/javascript" src="/static/admin/js/core.js"></script>
<script type="text/javascript" src="/static/vendor/select2/dist/js/select2.full.js"></script>
<script type="text/javascript" src="/static/admin/js/admin/RelatedObjectLookups.js"></script>
<script type="text/javascript" src="/static/vendor/select2/dist/js/i18n/en.js"></script>
<script type="text/javascript" src="/static/admin/js/actions.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/autocomplete.init.js"></script>
<script type="text/javascript" src="/static/admin/js/urlify.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/forward.js"></script>
<script type="text/javascript" src="/static/admin/js/prepopulate.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/select2.js"></script>
<script type="text/javascript" src="/static/admin/js/vendor/xregexp/xregexp.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/jquery.post-setup.js"></script>
.....
Built with 3.5.1:
<!DOCTYPE html>
<html lang="en-us" >
<head>
<title>Add Organization settings | Django site admin</title>
<link rel="stylesheet" type="text/css" href="/static/admin/css/base.css">
<link rel="stylesheet" type="text/css" href="/static/admin/css/forms.css">
<script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.js"></script>
<script type="text/javascript" src="/admin/jsi18n/"></script>
<link href="/static/vendor/select2/dist/css/select2.css" type="text/css" media="screen" rel="stylesheet">
<link href="/static/admin/css/autocomplete.css" type="text/css" media="screen" rel="stylesheet">
<link href="/static/autocomplete_light/select2.css" type="text/css" media="screen" rel="stylesheet">
<script type="text/javascript" src="/static/autocomplete_light/jquery.init.js"></script>
<script type="text/javascript" src="/static/admin/js/jquery.init.js"></script>
<script type="text/javascript" src="/static/vendor/select2/dist/js/select2.full.js"></script>
<script type="text/javascript" src="/static/admin/js/core.js"></script>
<script type="text/javascript" src="/static/vendor/select2/dist/js/i18n/en.js"></script>
<script type="text/javascript" src="/static/admin/js/admin/RelatedObjectLookups.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/autocomplete.init.js"></script>
<script type="text/javascript" src="/static/admin/js/actions.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/forward.js"></script>
<script type="text/javascript" src="/static/admin/js/urlify.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/select2.js"></script>
<script type="text/javascript" src="/static/admin/js/prepopulate.js"></script>
<script type="text/javascript" src="/static/autocomplete_light/jquery.post-setup.js"></script>
<script type="text/javascript" src="/static/admin/js/vendor/xregexp/xregexp.js"></script>
.....
Things work fine with 3.5.0. If you use 3.5.1 things break, and if you then substitute the 3.5.0 header (via Chrome dev tools overrides) it’ll work again.
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 16
- Comments: 22 (11 by maintainers)
Hello @jpic sorry for closing the issue I pressed the wrong button!
I tried 3.7.0.dev0 im my project (django 3.0.8) and it seems to be working fine (without using any custom media in my admin form). Thank you for the great work !
Thank you all for the great work 👍
⚠️ Disclaimer: ⚠️ Please excuse any mistakes I might have done below. I am quite new to Django and JavaScript, but I am trying to put my two cents in anyway. 😄
In my opinion, the initial issue report seems to highlight the crux of the problem: the absence of any constraints that determine the order of
'admin/js/jquery.init.js'
and'autocomplete_light/jquery.init.js'
. As far as I understand, this means that we are relying on internal details in Django’s stable topological sort algorithm, which seems to have been producing undesirable ordering since the removal of'admin/js/vendor/jquery/jquery.js'
in release3.5.1
(which, ideally, shouldn’t have any effect on the ordering of the aforementioned jquery init files).I also took a look at the new approach the library seems to be heading into currently in the master branch (that is, the removal of
'autocomplete_light/jquery.init.js'
, and making the other scripts more lenient on how they access jQuery). However, in my opinion, this shifts the ordering problem to'admin/js/vendor/select2/select2.full.js'
and'admin/js/jquery.init.js'
. With no constrains in place, Django is free to place any of them before the other and dal still requires that the former be loaded before the latter in order to work. Despite that the approach seems to be working at the moment, a seemingly unrelated change might cause Django to change the order later and suddenly break things (similar to what happened in release3.5.1
).Personally, I worked around this issue in
3.5.1
, by adding aMedia
class to my admin forms/classes that adds the missing constraint:I understand that this is impossible to include in the library, because it breaks
Select2WidgetMixin
when used outside django-admin. Therefore, I am proposing that the library includes a mixin that adds a similarMedia
class, and documents that the user is responsible for inheriting this mixin in their admin forms/classes in order to insert the missing constraint (i.e. similar to how the documentation currently instructs the user to make sure jQuery is properly included when using the library outside of the admin).Thank you very much, any feedback is appreciated…
In my case (#1143 ), the problem appears in
3.5.1
and continues unsolved, when an inline with aDAL
field coexists with an inline with adjango admin autocomplete
field, even when I provide explicitly the JQuery file in theMedia
metaclass of the relevant form:Awesome, releasing 3.7.0 this week.
Thanks to @danielmorell for the great work 😃
@jpic So I logged into work and found the discussion we had about this back in Feb, and using that I was able to replicate the same conditions.
3.6.0dev1 seems to work - the only oddity versus 3.5.0 in the inspection window is that there is a failed attempt to load
<site>/static/autocomplete_light/jquery.init.js
, followed by a successful attempt to load<site>/static/admin/js/jquery.init.js
.Here’s the page header with 3.5.0. (This virtually identical to how 3.5.0 looked when I originally reported this, with the recent addition of “inlines” and the fact that some of these items are minified now):
/static/autocomplete_light/jquery.init.js
is presentHere’s the page header with 3.6.1dev1 in use:
/static/autocomplete_light/jquery.init.js
is ABSENTI’m going to try more with this this coming week (I want to replicate the original problem before I call this done, and it was a very busy week). I’m pretty sure it’s working, but I want to make sure I’m actually exercising the right part of the system.
I’m curious what the situation is in this comment:
https://github.com/yourlabs/django-autocomplete-light/issues/1143#issuecomment-601919205
It’d be good to know if this solves the problem for them too.