Search code examples
pythondjangodjango-admindjango-ajax-selects

Django-ajax-selects with AJAX_SELECT_BOOTSTRAP = False


At work we are using django-admin webapp. I wanted to implement django-ajax-selects functionality to some of fields. Our network is isolated from Internet and I cannot use django-ajax-selects's CDNs. Documentation says that in such case you should set AJAX_SELECT_BOOTSTRAP to False in settings.py file. However, when I set this parameter, django-ajax-selects fails to use django's jquery. Django's version is 1.11.10, Python2.

Steps to reproduce my issue:

pip install django==1.11.10 django-ajax-selects
django-admin startproject proj ./
python manage.py startapp test_app
python manage.py migrate
python manage.py createsuperuser

test_app/models.py

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models


class Tag(models.Model):
    name = models.CharField(max_length=100)
    something = models.CharField(max_length=100)

    def __str__(self):
        return self.name


class SecondModel(models.Model):
    name = models.CharField(max_length=200)
    tag = models.ForeignKey(Tag, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

test_app/lookups.py

from ajax_select import register, LookupChannel
from .models import Tag

@register('tags')
class TagsLookup(LookupChannel):

    model = Tag

    def get_query(self, q, request):
        return self.model.objects.filter(name__icontains=q)

    def format_item_display(self, item):
        return u"<span class='tag'>%s</span>" % item.name

test_app/admin.py

# -*- coding: utf-8 -*-
from django.contrib import admin
from ajax_select import make_ajax_form
from .models import Tag, SecondModel


@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
    fields = ['name', 'something']


@admin.register(SecondModel)
class SecondModelAdmin(admin.ModelAdmin):

    form = make_ajax_form(SecondModel, {
        'tag': 'tags'
    })

proj/settings.py - adding the app and ajax_select to INSTALLED_APPS

INSTALLED_APPS = (
    ...
    'ajax_select',
    'test_app',
)

proj/urls.py

from django.conf.urls import url, include
from django.contrib import admin
from ajax_select import urls as ajax_select_urls

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^ajax_select/', include(ajax_select_urls)),
]

Then

python manage.py makemigrations test_app
python manage.py migrate

If I run the server like that it works absolutely fine (because it uses CDNs to load jquery and stuff). But if I set AJAX_SELECT_BOOTSTRAP to False I will get a TypeError in browser's console and the ajax functionality will not work. I guess ajax_select.js just loads before django's jquery was loaded. I could not figure it out, how can I specify load order or may be there is another way? Template overriding would be not very good idea as there is some overriding already used by other apps and I'm afraid it can cause some conflicts.


Solution

  • In the end what I needed to do was to manually download jquery.min.js, jquery-ui.js, jquery-ui.css and also jquery-ui images library, put them into app's static directory and point to them in admin.py:

    admin.py

    ...
    @admin.register(SecondModel)
    class SecondModelAdmin(admin.ModelAdmin):
        form = SecondModelForm
    
        class Media:
            js = ["/static/js/jquery.min.js",
                  "/static/js/jquery-ui.js"]
            css = {'all': ["/static/css/jquery-ui.css"]}
    

    Also don't forget to run python manage.py collectstatic for static files to be copied to common static directory.