amuttsch
amuttsch

Reputation: 1244

How to include js and css only once

I'm currently working on a template tag that renders forms nicely.

@register.inclusion_tag('myforms.html', takes_context=True)
def myform(context, form)
    context['form'] = form
    context['error_classes'] = 'has-error has-feedback'

    return context

In myforms.html, I use some JavaScript libraries and css files. In the template I added the scripts:

<link rel="stylesheet" href="{% static 'xyz.css' %}"/>
<script lang="javascript" src="{% static 'xyz.js' %}"></script>
<div>
   ...
</div>

When rendering multiple forms on a singe site, those <links> and <script> are multiple times in the html document.

One possibility is to include them in the base template inside the <head> tag. But then they are in the html file even when they aren't needed.

Adding a {{ block head }} to the base template inside the <head> doesn't work either. For this {{ block.super }} is needed to append new js and css files, but {{ block.super }} doesn't work in includes (see https://stackoverflow.com/a/6566463/2014080).

Upvotes: 1

Views: 273

Answers (2)

spectras
spectras

Reputation: 13562

I am a bit curious as to why you use includes. Although they do have some use cases, you should not be using them a lot. Anyway.

Django forms happen to have a feature that enables collecting assets Basically, you should define form-specific media directly on the form, like this:

class MyForm(ModelForm):
    # whatever you have there, then
    class Media:
        css = {
            'screen': ('foo.css', 'bar.css'),
        }
        js = ('jquery.js', 'myform.js')

The point is they are collected by Django, and you can manipulate them in your view or your templatetag, or wherever you have access to all your forms. Suppose you have MyForm and MyOtherForm, you can do:

context['form_media'] = my_form.media + my_other_form.media

And the, in your root template, you can just do:

<head>
    {{ form_media }}
</head>

As long as you stick to this convention in all your views.

Upvotes: 2

Mischback
Mischback

Reputation: 851

django-sekizai should do the trick. With the tags provided by this app you can dynamically add script or media-resources to your document. Be sure to check the docs, too.

Upvotes: 0

Related Questions