Skip to main content
 首页 » 编程设计

python之Django聚合外键的最高值

2025年05月04日35over140

我有看起来像这样的 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 功能或其他方式执行此操作的任何想法?重组模式的解决方案也很受欢迎。

请您参考如下方法:

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

  • 您知道无法在注释上编写过滤器。
  • 您可以编写解决方案 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() 

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