Skip to main content
 首页 » 编程设计

python之如何为一对多关系中的反向关系编写 Django ORM 查询

2024年08月14日43bonelee

我正在使用 Django 和 Python 3.7。我的 models.py 文件中有以下两个模型 ...

class Article(models.Model): 
    created_on = models.DateTimeField(default=datetime.now) 
... 
 
 
class ArticleStat(models.Model): 
    article = models.ForeignKey(Article, on_delete=models.CASCADE, ) 
    elapsed_time_in_seconds = models.IntegerField(default=0, null=False) 

我想编写一个 Django ORM 查询,我在其中选择文章的统计信息至少存在 5 分钟(300 秒)。但是,我不知道如何从 Article 对象引用 ArticleStat 对象。不出所料,这

Article.objects.filter(articlestat.elapsed_time_in_seconds.lte==300) 

产生一个

NameError: name 'articlestat' is not defined 

错误。

编辑:根据答案,我将 ArticleStat 模型更改为

class ArticleStat(models.Model): 
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articlestats') 

然后我运行下面的查询得到显示的错误

Article.objects.filter(articlestat_set__elapsed_time_in_seconds__lte==300) 
Traceback (most recent call last): 
  File "<input>", line 1, in <module> 
NameError: name 'articlestat_set__elapsed_time_in_seconds__lte' is not defined 

以为可能有一个复数的实例,所以我尝试了一个“s”,但得到了一个错误..

Article.objects.filter(articlestats_set__elapsed_time_in_seconds__lte==300) 
Traceback (most recent call last): 
  File "<input>", line 1, in <module> 
NameError: name 'articlestats_set__elapsed_time_in_seconds__lte' is not defined 

请您参考如下方法:

这里的核心问题是 articlestat 的 NameError,因此我将首先解决它。

如 django documentation 中所述默认情况下,您的反向关系名称定义为 FOO_set,在您的情况下,这意味着 articlestat_set。

If a model has a ForeignKey, instances of the foreign-key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set, where FOO is the source model name, lowercased.

如果您喜欢不同的名称,可以通过指定 related_name 来实现在您的 ForeignKey 定义中,例如

class ArticleStat(models.Model): 
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articlestats') 
    elapsed_time_in_seconds = models.IntegerField(default=0, null=False) 

第二个问题是如何正确遵循关系,解释得相当广泛here这就是为什么我不会在这个答案中详细介绍它。要点是您要使用 __ (双下划线)而不是 . 运算符。 field lookups也是如此您需要在此查询中进行比较。

解决了这两个问题后,您的查询应如下所示:

Article.objects.filter(articlestat_set__elapsed_time_in_seconds__lte=300) 

或使用自定义 related_name 例如related_name='articlestats':

Article.objects.filter(articlestats__elapsed_time_in_seconds__lte=300)