在Django管理面板中可以过滤外键的选项吗?
这是我的情况:
我有三个模型:成绩(Grade)、课程(Course)和项目(Program)。成绩模型里有一个指向课程的外键,而课程模型里又有一个指向项目的外键。
这是我的问题:
当我在管理面板中需要添加一些成绩时,我有一个课程的列表框。第一个问题是:同样的课程名称可能出现在两个不同的项目中,这让人很难在列表框中识别。目前显示的格式是“项目名称 - 课程名称”。
我在想有没有什么办法可以在我想要创建或修改成绩时,根据项目来过滤我的课程列表。(我说的是成绩创建界面,而不是在那个界面之前的列表)。
编辑:
谢谢大家的回答。我想我得自己编写一个小工具,用AJAX来实现客户端的过滤。
2 个回答
我遇到过类似的问题,这里是我找到的解决办法:
在课程的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)' 这样的内容。
你可以用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.TabularInline
或admin.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)