如何在管理页面上调整 django ManyToManyField 小部件的大小
how to resize django ManyToManyField widget on admin page
我正在尝试调整 django 1.8 admin 的多对多字段的大小。
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";
};
如您所见,我尝试了 3 种方法:
1:使用 formfield_overrides。没有任何区别。
2: 加载一个 javascript 来调整 html 对象的大小。它正在启动但没有调整它的大小,因为脚本似乎 运行 在加载小部件之前。
3:使用get_form。如下所示,它只调整 select 个框之一的大小。
有谁知道如何水平调整它的大小?
更新:
我发现:
class PenAdmin(admin.ModelAdmin):
formfield_overrides = {
models.ManyToManyField: {'widget': SelectMultiple(attrs={'size':'5', 'style': 'color:blue;width:250px'})},
}
可以使用,因为我删除了 filter_horizontal,但我想使用 filter_horizontal!
如果我没记错的话,filter_horizontal 选项将使用 MultiWidget,它显然没有将覆盖属性传递给子小部件。
不过,我认为必须有一个解决方案,我可以在页面加载后 运行 a javascript 。
请帮忙
您可以通过覆盖 CSS 样式来调整小部件的大小。
您需要覆盖以下 CSS 类:
.selector
- 这个 div 包含两个小部件。
.selctor-available
- 此 div 包含左侧的小部件。
.selector-chosen
- 这个 div 包含右侧的小部件。
首先,在项目的 static
目录中创建一个名为 resize-widget.css
的 CSS 文件。将以下代码添加到文件中:
更新: 对于 Django v2,这些 CSS 规则将不起作用。见 .
.selector-available,
.selector-chosen {
width: 200px;
}
.selector .selector-available input {
width: 184px;
}
.selector select {
width: 200px;
}
.selector {
width: 450px;
}
在 admin.py 中,通过 class Media
:
提供 CSS 文件
@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',)`
}
访问管理站点。 select 小部件必须如下所示:
我尝试了 xyres 答案,发现它有效,但一些 CSS 规则被使用更具体选择器的其他规则覆盖。
为了解决这个问题,我将 resize-widget.css
修改为以下内容:
.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;
}
这些更具体的规则没有被覆盖,因此对我有用。
有一种更简单的方法,就是覆盖 formfield_for_manytomany
def formfield_for_manytomany(self, db_field, request, **kwargs):
form_field = super().formfield_for_manytomany(db_field, request, **kwargs)
if db_field.name in [*self.filter_horizontal]:
form_field.widget.attrs={'size': '10'}
return form_field
我正在尝试调整 django 1.8 admin 的多对多字段的大小。
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";
};
如您所见,我尝试了 3 种方法:
1:使用 formfield_overrides。没有任何区别。
2: 加载一个 javascript 来调整 html 对象的大小。它正在启动但没有调整它的大小,因为脚本似乎 运行 在加载小部件之前。
3:使用get_form。如下所示,它只调整 select 个框之一的大小。
有谁知道如何水平调整它的大小?
更新: 我发现:
class PenAdmin(admin.ModelAdmin):
formfield_overrides = {
models.ManyToManyField: {'widget': SelectMultiple(attrs={'size':'5', 'style': 'color:blue;width:250px'})},
}
可以使用,因为我删除了 filter_horizontal,但我想使用 filter_horizontal! 如果我没记错的话,filter_horizontal 选项将使用 MultiWidget,它显然没有将覆盖属性传递给子小部件。 不过,我认为必须有一个解决方案,我可以在页面加载后 运行 a javascript 。 请帮忙
您可以通过覆盖 CSS 样式来调整小部件的大小。
您需要覆盖以下 CSS 类:
.selector
- 这个 div 包含两个小部件。.selctor-available
- 此 div 包含左侧的小部件。.selector-chosen
- 这个 div 包含右侧的小部件。
首先,在项目的 static
目录中创建一个名为 resize-widget.css
的 CSS 文件。将以下代码添加到文件中:
更新: 对于 Django v2,这些 CSS 规则将不起作用。见
.selector-available,
.selector-chosen {
width: 200px;
}
.selector .selector-available input {
width: 184px;
}
.selector select {
width: 200px;
}
.selector {
width: 450px;
}
在 admin.py 中,通过 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',)`
}
访问管理站点。 select 小部件必须如下所示:
我尝试了 xyres 答案,发现它有效,但一些 CSS 规则被使用更具体选择器的其他规则覆盖。
为了解决这个问题,我将 resize-widget.css
修改为以下内容:
.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;
}
这些更具体的规则没有被覆盖,因此对我有用。
有一种更简单的方法,就是覆盖 formfield_for_manytomany
def formfield_for_manytomany(self, db_field, request, **kwargs):
form_field = super().formfield_for_manytomany(db_field, request, **kwargs)
if db_field.name in [*self.filter_horizontal]:
form_field.widget.attrs={'size': '10'}
return form_field