【问题标题】:Accessing one model from within another in Django many-to-one using ForeignKey在 Django 中使用 ForeignKey 从另一个模型中多对一访问一个模型
【发布时间】:2021-07-08 13:19:53
【问题描述】:

假设我们有两个模型(多对一模型)。 下面的代码显示一个记者可以有多篇文章

class Reporter(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    email = models.EmailField()

    def __str__(self):
        return "%s %s" % (self.first_name, self.last_name)

class Article(models.Model):
    headline = models.CharField(max_length=100)
    pub_date = models.DateField(null=True)
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE, null=True)

    def __str__(self):
        return self.headline

让我们看看我的数据库中关于这个模型的内容。

# Reporter.objects.all().values()
# <QuerySet [
# {'id': 1, 'first_name': 'John', 'last_name': 'Smith', 'email': 'john@example.com'},
# {'id': 2, 'first_name': 'Paul', 'last_name': 'Jones', 'email': 'paul@example.com'}
# ]>
# Article.objects.all().values()
# <QuerySet [
# {'id': 5, 'headline': "1st headline", 'pub_date': datetime.date(2005, 7, 29), 
# 'reporter_id': 1},
# {'id': 6, 'headline': "2nd headline", 'pub_date': datetime.date(2006, 1, 17), 
# 'reporter_id': 2},
# {'id': 7, 'headline': '3rd headline', 'pub_date': datetime.date(2005, 7, 27), 
# 'reporter_id': 1}
# ]>

第一个记者有两个出版物,第二个只有一个。 我需要为每个记者获取所有文章的列表。 我试过这种方式(根据 django 文档):

Article.objects.filter(reporter__first_name='John')

没关系。有用。我还尝试将第一个记者实例化为“r1”,然后执行以下操作:

r1.article_set.all()

这段代码也有效。 但由于我是 django 新手,我认为将第一个记者实例化为 'r1' 然后进行查询有点慢。这是因为 django 让我运行 r1.save(),然后运行 ​​r1.article_set.all()。看起来 django 对数据库进行了 2 个查询(第一个查询 - 保存实例,第二个查询运行 r1.article_set.all)

我的观点正确吗?以及如何像 Article.objects.filter(reporter__first_name='John') 但使用 Reporter 对象查询所有记者的文章? 谢谢

【问题讨论】:

    标签: django django-models django-orm many-to-one


    【解决方案1】:

    我还尝试将第一个记者实例化为“r1”,然后执行以下操作:

    r1.article_set.all()
    

    这段代码也有效。但由于我是 django 新手,我认为将第一个记者实例化为 'r1' 然后进行查询有点慢。

    是的,但是 Django 可以通过 bulk 中的第二个查询来加载所有相关文章。我们使用.prefetch_related(…) [Django-doc] 来做到这一点:

    reporters = Reporter.objects.prefetch_related('article_set')
    
    for reporter in reporters:
        print(reporter.first_name)
        print(reporter.article_set.all())

    而不是您的实现进行的 N+1 个查询(一个查询来获取所有报告者,一个查询 per 个报告者来获取相关文章),这将进行 两个 查询:一个获取所有记者,一个获取与这些记者之一相关的所有文章。然后 Django 会进行一些加入,这样与第一个记者 r<sub>1</sub> 相关的文章最终会出现在 r<sub>1</sub>.article_set.all()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-02
      • 1970-01-01
      • 2017-04-17
      • 2011-09-19
      • 2021-05-29
      • 1970-01-01
      相关资源
      最近更新 更多