在Django管理面板中可以过滤外键的选项吗?

3 投票
2 回答
1095 浏览
提问于 2025-04-16 18:12

这是我的情况:
我有三个模型:成绩(Grade)、课程(Course)和项目(Program)。成绩模型里有一个指向课程的外键,而课程模型里又有一个指向项目的外键。

这是我的问题:
当我在管理面板中需要添加一些成绩时,我有一个课程的列表框。第一个问题是:同样的课程名称可能出现在两个不同的项目中,这让人很难在列表框中识别。目前显示的格式是“项目名称 - 课程名称”。

我在想有没有什么办法可以在我想要创建或修改成绩时,根据项目来过滤我的课程列表。(我说的是成绩创建界面,而不是在那个界面之前的列表)。

编辑:
谢谢大家的回答。我想我得自己编写一个小工具,用AJAX来实现客户端的过滤。

2 个回答

0

我遇到过类似的问题,这里是我找到的解决办法:

在课程的ModelAdmin中,为成绩定义一个InlineModelAdmin。

class CourseAdmin(admin.ModelAdmin):
    class GradeInline(admin.StackedInline):
        model = Grade
        fk_name = 'course'
        extra = 2
        and so on

这样,你就可以在对应课程的修改页面中添加和编辑成绩,而不需要再选择课程了。

为了在列表中区分不同项目的课程,我会重新定义 course.__unicode__,让它返回类似 'grade.name (program.name)' 这样的内容。

0

你可以用AJAX来写这样的过滤器(用jQuery或者类似的框架会是最简单的方法)。你需要创建一个自定义的表单小部件,里面有两个列表。第一个列表在页面加载时由服务器填充,显示所有可用的项目。然后你的JavaScript会等待用户选择一个项目,接着向服务器请求该项目下的课程列表,并相应地更新第二个列表。

不过,对于你的情况来说,这样做有点复杂;其实更简单的方法是按照jammon的回答,把成绩模型的管理放在对应课程的管理里面(这叫做内联模型管理;具体可以参考Django文档)。不幸的是,他们回答中的示例代码并不好用,所以我创建了下面这个对我有效的示例。

配置Django管理的基本方法就是在admin.py中注册你的模型。你可能正在做类似下面的事情:

from django.contrib import admin
from myapp.models import Program, Course, Grade

admin.site.register(Program)
admin.site.register(Course)
admin.site.register(Grade)

不过,我们想要在课程的管理部分内部编辑课程的成绩。首先,我们需要为成绩定义一个内联管理类:

class GradeInline(admin.TabularInline):
    model = Grade
    extra = 1

注意,你可以选择继承admin.TabularInlineadmin.StackedInline。通常,我更喜欢TabularInline的外观,但这也取决于你的模型,所以可以试试两者。extra选项定义了用户会看到多少个空表单。

接下来,我们需要告诉课程的管理页面添加内联表单:

class CourseAdmin(admin.ModelAdmin):
    model = Course
    inlines = (GradeInline,)

最后,我们不再想显示独立的成绩管理,所以不需要把它注册到管理网站上。相反,我们必须指定使用我们自定义的管理类来管理课程模型。这意味着应用程序的最终admin.py文件如下:

from django.contrib import admin
from myapp.models import Program, Course, Grade

class GradeInline(admin.TabularInline):
    model = Grade
    extra = 1

class CourseAdmin(admin.ModelAdmin):
    model = Course
    inlines = (GradeInline,)

admin.site.register(Program)
admin.site.register(Course, CourseAdmin)

撰写回答