How to resize django ManyToManyField Widget on admin page

I am trying to resize many django 1.8 admin fields.

models.py

from django.db import models class Material(models.Model): type = models.CharField(max_length=20, primary_key=True) def __unicode__(self): return self.type class Pen(models.Model): label = models.CharField(max_length=20, blank=True, default='') materials = models.ManyToManyField(Material) 

admin.py

 from django.contrib import admin from django.conf.urls import url from .models import * from django.forms import SelectMultiple @admin.register(Pen) class PenAdmin(admin.ModelAdmin): filter_horizontal = ('materials',) #formfield_overrides = { models.ManyToManyField: {'widget': SelectMultiple(attrs={'size':'5', 'width': '50px', 'style': 'width:50px'})}, } def get_form(self, request, obj=None, **kwargs): form = super(PenAdmin, self).get_form(request, obj, **kwargs) form.base_fields['materials'].widget.attrs['style'] = 'width: 70px;' return form class Media: js = ("js/resize_fields.js",) @admin.register(Material) class MaterialAdmin(admin.ModelAdmin): pass 

resize_fields.js

 document.onload = function() { document.getElementById("id_materials_to").style.width="70px"; }; 

As you can see, I tried 3 approaches:

1: using formfield_overrides. It didn't make any difference.

2: loading javascript to resize the html object. It launches, but does not change its size, since the script seems to run before the widget loads.

3: using get_form. As shown below, it only resizes one of the selection fields.

enter image description here

Does anyone know how to resize horizontally?

UPDATE: I found that:

 class PenAdmin(admin.ModelAdmin): formfield_overrides = { models.ManyToManyField: {'widget': SelectMultiple(attrs={'size':'5', 'style': 'color:blue;width:250px'})}, } 

will work since I deleted filter_horizontal, but I want to use filter_horizontal! If I'm not mistaken, the filter_horizontal parameter will use a MultiWidget, which apparently does not pass override attributes for the sub-sections. However, I think there should be a solution where I can run javascript after the page loads. Help plz

+7
django admin
source share
2 answers

You can resize the widget by overriding CSS styles.

You need to override the following CSS classes:

  • .selector - this div contains both widgets.

  • .selctor-available - this div contains the widget on the left.

  • .selector-chosen - this div contains the widget on the right.

First create a CSS file called resize-widget.css inside your static project. Add the following code to the file:

 .selector-available, .selector-chosen { width: 200px; } .selector .selector-available input { width: 184px; } .selector select { width: 200px; } .selector { width: 450px; } 

In admin.py put this CSS file through class Media :

 @admin.register(Pen) class PenAdmin(admin.ModelAdmin): filter_horizontal = ('materials',) class Media: css = { 'all': ('resize-widget.css',), # if you have saved this file in `static/css/` then the path must look like `('css/resize-widget.css',)` } 

Visit the admin site. The selection widget should look like this:

enter image description here

+5
source share

I tried answering xyres and found that it worked, but some CSS rules were overridden by other rules that used more specific selectors.

To fix this, I changed resize-widget.css to the following:

 .form-horizontal .control-group .controls .selector { width: 100%; } .form-horizontal .control-group .controls .selector .selector-available, .form-horizontal .control-group .controls .selector .selector-chosen { max-width: 45%; } .form-horizontal .control-group .controls .selector select { min-height: 200px; } 

These more specific rules were not overridden and made me work for me.

0
source share

All Articles