按Django ModelAdmin变更列表中的聚合外部字段排序



在我当前的项目中,我试图在Django中建立一个简单的测试应用程序。对于管理,我使用生成的Django管理员,但我很难在模型的变更列表视图中包含一个具有最佳测试结果的可排序计算字段。

我的模型如下(简化(:

class Candidate(models.Model):
name = models.CharField(max_length=255, null=False)
email = models.EmailField(unique=True, null=False)
class Test(models.Model):
candidate = models.ForeignKey(Candidate, on_delete=models.CASCADE, null=False)
result = models.PositiveIntegerField(null=True)
class Question(models.Model):
text = models.TextField(null=False)
correct_answer = models.CharField(max_length=1, choices=OPTIONS, null=False)
class Answer(models.Model):
test = models.ForeignKey(Test, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='answers')
answer = models.CharField(max_length=1, choices=Question.OPTIONS, null=True)

一个候选人可能有多个测试,我想在变更列表视图中显示一个具有最佳结果的字段,并能够根据它进行排序。结果是使用相同测试FK的所有答案中正确答案的百分比(Answer.question.correct_answer == Answer.answer(。

发现我无法使用函数定义的自定义计算字段,因为Django无法根据它进行排序,因为排序需要修改直接转换为SQL的queryset。因此,我添加了带有计算百分比的Test.result字段(这将方案反规范化://(,并尝试在queryset中为每个候选添加带有SELECT MAX(Test.result) FROM Test WHERE Test.candidate = {candidate}的注释字段,但找不到方法。

问题是,查询需要反向外键映射,因为候选者:test的1:M映射,我还没有找到如何实现它的方法

class CandidateAdmin(admin.ModelAdmin):
list_display = ['name', 'email','best_result']
search_fields = ['name', 'email']
def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.annotate(
_best_result = models.Max('tests_result')
)
return queryset
def best_result(self, obj):
return obj._best_result

但是Django不理解我在tests_result的反向外键搜索中使用MAX的尝试。你能给我个建议吗?或者,如果我错过了如何添加自定义排序的方法,这样我就不需要在数据库中保留计算出的测试结果,同时仍按它进行排序,我将感谢任何提示。

最后,我用查询创建了一个数据库视图,将它添加到Meta中带有managed = False的模型中,并使用它。工作起来很有魅力。

最新更新