【问题标题】:Change Django autocomplete_fields label更改 Django autocomplete_fields 标签
【发布时间】:2019-04-11 10:05:43
【问题描述】:

我正在尝试为autocomplete_fields 中某个类型的所有项目设置自定义标签。

到目前为止,对于下拉列表,人们会使用

...
class CustomDisplay(forms.ModelChoiceField):
    def label_from_instance(self, obj):
        return "Some custom text: {}".format(obj.name)
...
somethings = CustomDisplay(queryset=Something.object.all())
...

但将其与 autocomplete_fields = (somethings,) 一起使用将导致自动完成取消并向我显示带有自定义文本的下拉菜单。

【问题讨论】:

    标签: python django django-2.1


    【解决方案1】:

    该字段显示普通select 小部件的原因是,当您定义自定义字段时,您没有将小部件设置为AutocompleteSelect

    在您指定autocomplete_fieldsModelAdmin 类中,导入您的CustomDisplayAutocompleteSelect 并添加以下方法:

    from django.contrib.admin.widgets import AutocompleteSelect
    
    
    class YourModelAdmin(admin.ModelAdmin):
        autocomplete_fields = ['something']
    
        ...
    
        def formfield_for_foreignkey(self, db_field, request, **kwargs):
            db = kwargs.get('using')
    
            if db_field.name == 'something':
                return CustomDisplay(queryset=Something.object.all(), widget=AutocompleteSelect(db_field.remote_field, self.admin_site, using=db))
            return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    只有在您查看现有实例时才会显示自定义文本。当您查看自动完成下拉菜单并选择一个条目时,标签不是从label_from_instance() 生成的,而是从AutocompleteJsonView 内部的一个简单的str() 调用生成的。

    因此,假设您只想更改自动完成小部件中的标签(要全面更改标签,您显然只需更改模型__str()__ 方法),您还需要在admin.py 中创建一个自定义类修改AutocompleteJsonView中的get()方法:

    from django.contrib.admin.options import AutocompleteJsonView
    from django.http import Http404, JsonResponse
    
    class CustomAutocompleteJsonView(AutocompleteJsonView):
        def get(self, request, *args, **kwargs):
            if not self.model_admin.get_search_fields(request):
                raise Http404(
                    '%s must have search_fields for the autocomplete_view.' %
                    type(self.model_admin).__name__
                )
            if not self.has_perm(request):
                return JsonResponse({'error': '403 Forbidden'}, status=403)
    
            self.term = request.GET.get('term', '')
            self.paginator_class = self.model_admin.paginator
            self.object_list = self.get_queryset()
            context = self.get_context_data()
    
            # Replace this with the code below.
            #
            # return JsonResponse({
            #     'results': [
            #         {'id': str(obj.pk), 'text': str(obj)}
            #         for obj in context['object_list']
            #     ],
            #     'pagination': {'more': context['page_obj'].has_next()},
            # })
    
            return JsonResponse({
                'results': [
                    {'id': str(obj.pk), 'text': 'Some custom text: {}'.format(obj.name)}
                    for obj in context['object_list']
                ],
                'pagination': {'more': context['page_obj'].has_next()},
        })
    

    现在在自动完成显示结果的 ModelAdmin 类上设置 autocomplete_view(而不是您指定 autocomplete_fields 的 ModelAdmin 类):

    def autocomplete_view(self, request):
        return CustomAutocompleteJsonView.as_view(model_admin=self)(request)
    

    因此,如果您有一个名为 YourModelAdminautocomplete_fields = ['something']ModelAdmin 类,您将为您的 Something 模型设置相应的 ModelAdmin 类的 autocomplete_view

    【讨论】:

    • 哇!我永远不会想到这一点
    • 不幸的是,Django 3.2 将 autocomplete_viewModelAdmin 移出,我还没有弄清楚如何适应上面的(看起来很棒!)解决方案。如果我破解它,我会在这里发帖,但想警告其他读者这个解决方案可能不再按预期工作。
    猜你喜欢
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    • 2013-01-04
    • 2022-12-17
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 2016-02-11
    相关资源
    最近更新 更多