Django Admin:如何自定义 autocomplete_fields 宽度以适应内容?

Posted

技术标签:

【中文标题】Django Admin:如何自定义 autocomplete_fields 宽度以适应内容?【英文标题】:Django Admin: How to customize autocomplete_fields width to adapt to the content? 【发布时间】:2020-08-24 00:30:01 【问题描述】:

我正在尝试自定义由 autocomplete_fields 为 ForeignKey Model 字段呈现的小部件。 基本上问题是小部件对于内容来说太窄了,它在选择内分成两行:

我已经看到 JS 库或 JQuery 插件被称为 Select2 并且它有一个 "dropdownAutoWidth" 以使其适应父元素大小这种工作但我完全不知道如何从管理员设置该选项.py,因为似乎从未在 django.contrib.admin.widgets.AutocompleteMixin.media 的代码中传递选项:

    def media(self):
    extra = '' if settings.DEBUG else '.min'
    i18n_name = SELECT2_TRANSLATIONS.get(get_language())
    i18n_file = ('admin/js/vendor/select2/i18n/%s.js' % i18n_name,) if i18n_name else ()
    return forms.Media(
        js=(
            'admin/js/vendor/jquery/jquery%s.js' % extra,
            'admin/js/vendor/select2/select2.full%s.js' % extra,
        ) + i18n_file + (
            'admin/js/jquery.init.js',
            'admin/js/autocomplete.js',
        ),
        css=
            'screen': (
                'admin/css/vendor/select2/select2%s.css' % extra,
                'admin/css/autocomplete.css',
            ),
        ,
    )

【问题讨论】:

【参考方案1】:

Django 3.0.9:

forms.py

from django import forms
from django.contrib import admin
from django.contrib.admin.widgets import AutocompleteSelect

from .models import MyModel

    class MyModelForm(forms.ModelForm):
        class Meta:
            fields = ('my_field', )
            widgets = 
                'my_field': AutocompleteSelect(
                    MyModel.my_field.field.remote_field,
                    admin.site,
                    attrs='style': 'width: 400px'  # You can put any width you want.
                ),
            

admin.py

from django.contrib import admin

from .forms import MyModelForm


MyModelAdmin(admin.ModelAdmin):
    form = MyModelForm

【讨论】:

对于 models.ManyToManyField,要使用的小部件是 AutocompleteSelectMultiple 而不是 AutocompleteSelect。您也必须导入它 更新:Django 3.2 忘记了“remote_field”部分。【参考方案2】:

您可以通过将data-* attributes 包含在自动完成小部件的attrs 中来将它们传递给select2。一种方法是使用自定义表单自己初始化小部件。

请注意,如果您还在autocomplete_fields 中包含该字段,则小部件将由您的ModelAdmin 实例初始化,并且您的自定义初始化不会有任何效果。

另请注意,AutocompleteSelectAutocompleteSelectMultiple 小部件需要几个位置参数。

这样的事情应该可以工作:

from django import forms
from django.contrib import admin
from django.contrib.admin.widgets import AutocompleteSelect

class MyForm(forms.ModelForm):
    class Meta:
        widgets = 
            'my_field': AutocompleteSelect(
                MyModel._meta.get_field('my_field').remote_field,
                admin.site,
                attrs='data-dropdown-auto-width': 'true'
            ),
        

class MyAdmin(admin.ModelAdmin):
    #autocomplete_fields = ['my_field']
    form = MyForm

【讨论】:

感谢您的回答,我会试一试,但我认为您不能将所有属性作为 data-* 属性传递。 如果以这种方式传递,大多数 data-* 属性应该可以工作。不起作用的属性是硬编码到AutocompleteMixin 中的属性。您可能必须扩展小部件来修改它们。查看the source code。我已经在 Django 2.2 中使用 data-dropdown-auto-width 对此进行了测试,并且可以正常工作。 请注意,自动宽度仅适用于下拉菜单。如果要设置选择元素的宽度,请将“数据宽度”添加到 attrs。

以上是关于Django Admin:如何自定义 autocomplete_fields 宽度以适应内容?的主要内容,如果未能解决你的问题,请参考以下文章

Django admin:如何在单击自定义按钮时调用操作?

如何在 django-admin-tools 仪表板上添加自定义菜单项

如何使用 Django admin 使用 Celery 创建自定义任务

如何将额外的参数传递给 django admin 自定义表单?

如何更改 Django Admin 自定义列表字段标签

根据值在 Admin 中自定义 Django 表单字段