How are Django's form assets (Media class) served?

The "Form Assets" page of Django says

Django allows you to associate different files – like stylesheets and scripts – with the forms and widgets that require those assets. For example, if you want to use a calendar to render DateFields, you can define a custom Calendar widget. This widget can then be associated with the CSS and JavaScript that is required to render the calendar. When the Calendar widget is used on a form, Django is able to identify the CSS and JavaScript files that are required, and provide the list of file names in a form suitable for inclusion on your web page.

Okay, but what component of Django takes those form assets and actually puts them in the page?

I ask because I'm trying to use django-autocomplete-light (DAL) with django-bootstrap5 on a multi-select form with a many-to-many field. I've done all the installing, put the widget on my form field:

class SomeForm(forms.ModelForm):
    class Meta:
        model = Something
        fields = ['things']
        widgets = {
            'things': autocomplete.ModelSelect2Multiple(
                url='myapp:things-autocomplete')
        }

I know the widget url is correct because if it's wrong, Django barks. I know the widget is being put onto the field because it changes (from listing all things to a blank square).

I can see the HTML for the form widget includes autocomplete-light stuff to multi-select "things" with "things" autocomplete:

...
<select name="things" class="form-select" required id="id_things"
 data-autocomplete-light-language="en"
 data-autocomplete-light-url="/things-autocomplete/"
 data-autocomplete-light-function="select2" multiple>
</select>
...

However, I don't see anywhere that select2.js is included in this web page.

I used django-autocomplete-light's ModelSelect2Multiple, which has the Select2WidgetMixin that defines a media property with all kinds of good looking stuff:

        return forms.Media(
            js=(
                'admin/js/vendor/select2/select2.full.js',
                'autocomplete_light/autocomplete_light%s.js' % extra,
                'autocomplete_light/select2%s.js' % extra,
            ) + i18n_file,
            css={
                'screen': (
                    'admin/css/vendor/select2/select2%s.css' % extra,
                    'admin/css/autocomplete.css',
                    'autocomplete_light/select2.css',
                ),
            },
        )

I do not see any of that good-looking stuff in my web page.

I'm running with debug=True (dev mode) for now, so I believe that static files should be served as long as I have the django.contrib.staticfiles app in my settings, which I do.

Which Django component should be serving up DAL's media, and how?

I'm using Django 4.1, django-autocomplete-light 3.9.4, django-bootstrap5 22.2.

P.S. I saw other questions that seemed related, but not exactly this situation.

EDIT: It looks like form assets are loaded in a template with {{form.media}}. Maybe I have to put that media in the right place (the HTML head)?

I got this to work by adding a script block, and adding jquery and the form media manually:

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

Not sure if there's a more automatic way to include widget media.

Back to Top