【问题标题】:Django admin - using autocomplete and filter on choices fields (not ManyToMany or ForeignKey)Django admin - 使用自动完成和过滤选择字段(不是 ManyToMany 或 ForeignKey)
【发布时间】:2021-12-07 09:12:06
【问题描述】:

这是我的模型:

class Academic(models.Model):

SCHOOL_COLLEGE_SERVICE = [
    ('School Of Humanities', 'School Of Humanities'),
    ('School Of Culture & Creative Arts', 'School Of Culture & Creative Arts'),
    ('School Of Modern Languages & Cultures', 'School Of Modern Languages & Cultures'),
    ('School Of Critical Studies', 'School Of Critical Studies'),
    ('Arts  College Of Arts Administration', 'Arts  College Of Arts Administration'),
    ]

school = models.CharField(choices=SCHOOL_COLLEGE_SERVICE, max_length=50, blank=True, null=True)

我想在我的 Django 管理界面中有一个不错的自动完成/过滤器。不幸的是,如果数据集不是来自 ManyToMany 或 ForeignKey 关系,似乎不可能有自动完成功能。这是我尝试过的:

from django.contrib import admin
from .models import Academic, Partner, Project
from admin_auto_filters.filters import AutocompleteFilter
import django_filters

@admin.register(Academic)
class AcademicAdmin(admin.ModelAdmin):
    search_fields = ['surname', 'forename']
    #school = django_filters.ChoiceFilter(choices=Academic.SCHOOL_COLLEGE_SERVICE)
    #autocomplete_fields = ['school']

我知道我也可以像这样设置查询集:

class SchoolFilter(django_filters.FilterSet):
    class Meta:
        model = Academic
        fields = ['school',]

但是 Django 还是抱怨The value of 'autocomplete_fields[0]' must be a foreign key or a many-to-many field. 怎样才能实现我想要的呢?

【问题讨论】:

  • 您的实际模型/数据中是否有超过 5 所学校?
  • 这是选择之一。在这种特定情况下,我只有 5 个,在其他模型中,我什至有 20 或 30 个选择。

标签: python django django-admin django-filters django-admin-filters


【解决方案1】:

您可以使用 django-autocomplete-light 包轻松地将表单 choicefield 作为自动完成下拉菜单。这个包也支持查询集。

在forms.py中,

class AcademicForm(forms.ModelForm):
    SCHOOL_COLLEGE_SERVICE = [
    ('School Of Humanities', 'School Of Humanities'),
    ('School Of Culture & Creative Arts', 'School Of Culture & Creative Arts'),
    ('School Of Modern Languages & Cultures', 'School Of Modern Languages & Cultures'),
    ('School Of Critical Studies', 'School Of Critical Studies'),
    ('Arts  College Of Arts Administration', 'Arts  College Of Arts Administration'),
    ]
    school = forms.ChoiceField(choices=SCHOOL_COLLEGE_SERVICE,
                               widget=autocomplete.ListSelect2(url='school_autocomplete'))
    
    class Meta:
        model = Academic
        fields = ['school', 'other_your_model_fields']

在 urls.py 中,

urlpatterns = [
    path('school-autocomplete', SchoolAutocompleteView.as_view(), name='school_autocomplete'),
    ]

在views.py中,

from dal import autocomplete

class SchoolAutocompleteView(autocomplete.Select2ListView):

    def get_list(self):
        if not self.request.user.is_authenticated:
            return []

        SCHOOL_COLLEGE_SERVICE = ['School Of Humanities',
                                  'School Of Culture & Creative Arts',
                                  'School Of Modern Languages & Cultures',
                                  'School Of Critical Studies',
                                  'Arts  College Of Arts Administration']

        return SCHOOL_COLLEGE_SERVICE

现在您在管理类中使用 modelform,

@admin.register(Academic)
class AcademicAdmin(admin.ModelAdmin):
    form = AcademicForm
    ....
    ....

更多详情,doc_link-https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html

【讨论】:

  • 谢谢。这是否意味着我需要将我的 CHOICES 复制三次,即它们需要在我的 models.py、forms.py 和 views.py 中?
  • @HBMCS 您不需要在 models.py 中设置选项,也可以在 forms.py 中设置空选项,即 []。您仅在 views.py 中定义选择列表。我只是复制粘贴您的选择以便更好地理解。
  • @HBMCS 我编辑了我的答案。 从表单中删除选项
  • ~~好吧,如果我将浏览器指向学校自动完成网址,我确实有自己的选择。尽管如此,在管理界面中,选择字段是空的。~~ - 抱歉,我没有收集我的静态文件,也没有加载 JavaScript 文件。像魅力一样工作,谢谢!
  • 感谢您的努力;这是与 DRY 概念背道而驰的重复。不过现在它确实有效,我给你。在我看来,最好的解决方案几乎总是拥有一个带有外来/多对多键的单独模型。无论如何我都会接受你的回答,因为它最终确实有效,尽管我最终将使用一个单独的模型。
猜你喜欢
  • 2013-05-23
  • 2018-03-31
  • 2018-02-25
  • 2022-11-12
  • 1970-01-01
  • 1970-01-01
  • 2021-06-07
  • 1970-01-01
  • 2017-01-22
相关资源
最近更新 更多