新版Chrome中Django-autocomplete-light模态框表单渲染异常
问题描述
我有一个基于Python 3.7和Django 2.2.10的Django应用,使用Django Admin,模板采用Materialize CSS。自Chrome最新版本更新后,模态框中的表单出现渲染问题(其他浏览器可正常运行)。
自定义Widget代码
class Select2Widget(Select2WidgetMixin): def _get_language_code(self): return 'pt-BR' @property def media(self): """Return JS/CSS resources for the widget.""" return forms.Media( js=( 'autocomplete_light/jquery.init.js', STATIC_URL + 'js/select2.full.js', # 'vendor/select2/dist/js/select2.full.js', 'autocomplete_light/autocomplete.init.js', 'autocomplete_light/forward.js', 'autocomplete_light/select2.js', 'autocomplete_light/jquery.post-setup.js', ), css={ 'screen': ( 'vendor/select2/dist/css/select2.min.css', 'admin/css/autocomplete.css', 'autocomplete_light/select2.css', ), }, ) autocomplete_function = 'select2' """ retorna queryset na ordem que foi selecionado no field """ class QuerySetSelect(WidgetMixin): def filter_choices_to_render(self, selected_choices): preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(selected_choices)]) """Filter out un-selected choices if choices is a QuerySet.""" self.choices.queryset = self.choices.queryset.filter(pk__in=[c for c in selected_choices if c]).order_by(preserved) class ModelSelect2(QuerySetSelectMixin, Select2Widget, forms.Select): ... class ModelSelect2Multiple(QuerySetSelectMixin, Select2Widget, forms.SelectMultiple): ... class Select2Multiple(Select2Widget, SelectMultiple): ...
表单使用代码
class PessoaForm(ModelForm): ativo = forms.BooleanField(required=False) cpf_cnpj = BRCPFCNPJField(label='CPF/CNPJ', max_length=14) logradouro = forms.ModelChoiceField(queryset=Logradouro.objects, required=False, label='CEP', widget=ModelSelect2(url='logradouro_autocomplete', attrs={'data-placeholder': 'Informe o CEP', 'style': 'width: 100%;', 'data-minimum-input-length': 8, 'class':'material-ignore', 'material-ignore': True}),) municipio = forms.ModelChoiceField(queryset=Municipio.objects, label='Município', required=False, widget=ModelSelect2(url='logradouro_municipio_autocomplete', forward=['logradouro'], attrs={'style': 'width: 100%;', 'data-placeholder': 'Selecione', 'class': 'material-ignore', 'material-ignore': True })) local_emissao_cnh = forms.ModelChoiceField(queryset=Municipio.objects, label='Municipio Emissão da CNH', required=False, widget=ModelSelect2(url='logradouro_municipio_autocomplete', forward=['logradouro'], attrs={'style': 'width: 100%;', 'data-placeholder': 'Selecione', 'class': 'material-ignore', 'material-ignore': True })) bairro = forms.ModelChoiceField(queryset=Bairro.objects, label='Bairro', required=False, widget=ModelSelect2(url='bairro_autocomplete', forward=['municipio', 'logradouro'], attrs={'style': 'width: 100%;', 'data-placeholder': 'Selecione', 'class': 'material-ignore', 'material-ignore': True})) qualificacao = forms.ModelChoiceField(queryset=Qualificacao.objects, label='Qualificação', required=False, widget=ModelSelect2Multiple(url='qualificacao_autocomplete', attrs={'style': 'width: 100%;', 'data-placeholder': 'Selecione', 'class': 'material-ignore', 'material-ignore': True})) ocupacao = forms.ModelChoiceField(queryset=Qualificacao.objects, label='Ocupação', required=False, widget=ModelSelect2Multiple(url='ocupacao_autocomplete', attrs={'style': 'width: 100%;', 'data-placeholder': 'Selecione', 'class': 'material-ignore', 'material-ignore': True})) class Meta: fields = '__all__' model = Pessoa def __init__(self, *args, **kwargs): self.request = kwargs.pop('request', None) super(PessoaForm, self).__init__(*args, **kwargs) if self.instance.pk and self.instance.user: self.initial['is_active'] = self.instance.user.is_active self.initial['is_staff'] = self.instance.user.is_staff self.initial['grupos'] = self.instance.user.groups.all()
问题表现
Chrome最新版本中,模态框内的Select2表单控件渲染异常(如布局错乱、下拉框不显示或样式冲突),其他浏览器无此问题。已尝试更换相关库、社区搜索,均未解决。
可能的解决方案
1. 升级依赖库版本
Chrome新版本可能对DOM渲染、事件机制有更新,旧版Select2或django-autocomplete-light可能存在适配问题:
- 升级Select2到最新稳定版(当前为4.0.13+),替换项目中
select2.full.js和select2.min.css文件; - 同步升级django-autocomplete-light到兼容Django 2.2的最新版本,避免版本不匹配引发的冲突。
2. 修复样式冲突
Materialize与Select2的样式优先级在Chrome新版本中可能冲突,添加自定义CSS强制修正:
/* 确保模态框内Select2容器宽度正常 */ .modal .select2-container { width: 100% !important; z-index: 10000 !important; /* 避免被模态框遮罩覆盖 */ } /* 修复下拉框定位问题 */ .modal .select2-dropdown { z-index: 10001 !important; position: fixed !important; }
将上述代码添加到Admin自定义样式文件中,确保在Materialize和Select2样式之后加载。
3. 调整Select2初始化时机
Chrome可能修改了模态框shown事件的触发时机,导致Select2在模态框未完全渲染时初始化:
// 手动初始化Select2,确保模态框完全显示后执行 $(document).on('shown.bs.modal', '.modal', function() { $(this).find('.select2').select2({ language: 'pt-BR', dropdownParent: $(this) // 将下拉框挂载到模态框内,避免溢出或定位错误 }); });
同时移除Widget media中自动初始化的相关代码,改用上述手动初始化逻辑。
4. 检查jQuery版本兼容性
确保项目使用的jQuery版本与Select2、django-autocomplete-light兼容:
- Django 2.2默认jQuery为2.x版本,Select2 4.x兼容jQuery 1.8+,建议升级到jQuery 3.x稳定版;
- 替换项目中的jQuery文件,测试是否解决问题。
5. 临时禁用Chrome实验性特性
若问题由Chrome新特性导致,可临时禁用测试:
- 地址栏输入
chrome://flags/; - 搜索
LayoutNG或CSS Container Queries等布局相关特性,设置为Disabled; - 重启Chrome测试,若问题解决,等待库方发布适配补丁后再恢复特性。
内容的提问来源于stack exchange,提问作者Dev Orea
相关产品推荐
相关产品推荐

