Django汇总了外键的最高价值

时间:2011-02-18 20:02:56

标签: python django

我有看起来像这样的Django模型

class Solution(models.Model):
    score = models.IntegerField();
    data = models.TextField();

class SolutionAuthors(models.Model):
    sol = models.ForeignKey(Solution);
    user = models.ForeignKey(User);
    date_solved = models.DateField()

我希望查询每个解决方案的最新SolutionAuthor。

等效的SQL可能看起来像这样

SELECT * FROM Solutions s INNER JOIN SolutionAuthor sa ON sa.sol=s.sol
WHERE sa.id = ( SELECT TOP 1 sa_id FROM SolutionAuthor sa2 WHERE sa2.sol=s.sol
                ORDER BY date_solved )

有关如何使用annotate功能或其他方式执行此操作的任何想法?重新组织架构的解决方案也是受欢迎的。

1 个答案:

答案 0 :(得分:0)

你有> 8K代表,这意味着:

  • 您知道无法在注释上编写过滤器
  • 您可以撰写Solution model method 以获取最新解决方案。

这是一个带有模型方法的示例解决方案,不需要在查询中添加注释,因为您可以随时调用方法:

class Solution(models.Model):
    score = models.IntegerField()
    data = models.TextField()     

    @method
    def last_solution(self):
        return self.objects.solutionauthors_set.latest('date_solved')

如果不是这样,您的方法可能是因为性能问题,或者因为您无法在查询中通过模型方法包含过滤器。如果这是我的应用,我的解决方案是坚持上次solution author进入solution模型

class Solution(models.Model):
    score = models.IntegerField()
    data = models.TextField()     

    #new persisted field:
    last_solution = models.ForeignKey('SolutionAuthors', null=True, blanc=True);

#keeping last_solution up to date:
#imports to handle signals:
from django.db.models.signals import post_save
from django.dispatch import receiver

#persisting data
@receiver(post_save, sender=SolutionAuthors)
def set_last_solution(sender, instance, signal, created, **kwargs):
    if created or instance.date_solved > instance.sol.last_solution.date_solved:
        instance.sol.last_solution = instance
        instance.sol.save()

此方法将通过最后一个解决方案提高任何查询的性能。 的缺点是数据库的非规范化,但我认为必须改变对这一主题的态度。