Solution: using Many-to-Many horizontal interface outside of admin

755 views
Skip to first unread message

Jason McVetta

unread,
Aug 9, 2007, 6:38:00 PM8/9/07
to django...@googlegroups.com
A number of people, myself included, have asked this list how the admin interface's slick javascript many-to-many widget can be used in templates outside admin.  None of the answers given solved the issue for me, but they did point me in the right direction.  After a day of reading the source, I was able to get the widget to work with my templates.

Here's how I got it working:
  1. Get the right javascripts imported.  Two script files, "core.js" and "SelectFilter2.js", are needed.  Additionally, you must include the jsi18n view generated by admin interface; by default its url is "/admin/jsi18n". 

    <script type="text/javascript" src="/admin/jsi18n/"></script>
    <script type="text/javascript" src="/media/js/core.js"></script>
    <script type="text/javascript" src="/media/js/SelectFilter2.js"></script>


  2. Decorate your form field with the "vSelectMultipleField" class attribute.  For example, if you had created a form called "form" from your model, and the M2M field was called "foo", you would put this in your view:

    form.fields['foo'].widget.attrs['class'] = 'vSelectMultipleField'

  3. Include javascript in your template to initialize the widget.  For our "foo" example, you would insert this line somewhere after {{ form.foo }}:

    <script type="text/javascript">addEvent(window, "load", function(e) { SelectFilter.init("id_tags", "tags", 0, "/media/"); });</script>


    In the admin interface, inserting this code is handled by a template tag called "filter_interface_script_maybe".  That tag has admin-specific logic, but one could easily write a similar tag for one's own templates.

I hope that is helpful.





On 6/13/07, Jason McVetta <jason....@gmail.com > wrote:
Forgive this question if the answer is overly obvious; but I have not yet figured it out.  I want to use the horizontal M2M widget from the admin interface in my own template.  The model looks like something this:

class Foo(models.Model):
    bars = models.ManyToManyField(Bar, filter_interface=models. HORIZONTAL)

My views.py looks something like this:

def myView(request, object_id):
   foo = Foo.objects.filter(id=object_id)[0]
   FooForm = form_for_instance(foo)
   form = FooForm()
   rc = template.RequestContext(request)
   return render_to_response('path/to/mytemplate.html', {'form': form}, rc)

And my template includes a line like:

<p><label for="id_bars">Bars:</label> {{ form.bars }}</p>

While the model alone is sufficient to produce a horizontal filter in the admin interface, in my template all it displays is a basic HTML select multiple list. 

I suspect the answer lies in decorating the widget rendered by {{ form.bars }} with a class or id so the Javascript knows to beautify it, but I am not sure how to do so.  

Reply all
Reply to author
Forward
0 new messages