[Fixed]-Whats easiest way to use filter_horizontal outside of the Admin in Django

16👍

I know this thread is old, but hopefully this info will help someone else who stumbles upon this page like I did.

After much pain and suffering, I was able to get this to work with Django 1.4. Like rh0dium, I tried all those articles, but had to make a lot of tweaks.

You don’t have to do anything special with the ModelForm, but you do have to include all these js and css files in the template:

<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/core.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.min.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.init.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/SelectFilter2.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/SelectBox.js"></script>

<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/widgets.css"/>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/base.css"/>
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/forms.css"/>

Then render the form as you normally would, but you need to get the fieldset elements and class names right for the css to work. For example:

<fieldset>
    <div class="form-row">
        <form method="post" action=".">
            {% csrf_token %}
            {{ form.as_p }}
        <button type="submit" value="submit">Add</button>
    </form>
  </div>
</fieldset>

Then at the BOTTOM of the template (after the markup to render the form), add this script and replace pricetags with whatever your Many to Many (M2M) relationship name is on the model form’s model:

<script type="text/javascript">
    addEvent(window, "load", function(e) { SelectFilter.init("id_pricetags", "pricetags", 0, "{{ STATIC_URL }}admin/"); });
</script>

Apparently your media location may be something different, but {{ STATIC_URL }}admin/ worked for me.

4👍

I got this working very easily in Django 3 in 2020; perhaps things have changed since the question was asked in 2011. All I needed to do was set the widget of the form field, no custom Media defined on the class (django will add it automatically based on the widgets used):

class FooForm(forms.Form):
    linked_bars = forms.ModelMultipleChoiceField(queryset=Bar.objects.all(),
                         widget=widgets.FilteredSelectMultiple(Bar._meta.verbose_name_plural, False))
# end of class, no Media!

You DO need to have the jsi18n loaded globally so in a base template I have:

{% block extrahead %}
  {{ block.super }}
  <script type="text/javascript" src="/admin/jsi18n/"></script>
{% endblock %}

Leave a comment