Django: 如何使用Django ORM实现JOIN操作?

37

我在Django中建立了一个问答类型的网站,使用以下模型:

class Question(models.Model):
    title = models.CharField(max_length=70)
    details = models.TextField()

class Answer(models.Model):
    question_id = IntegerField()
    details = models.TextField()

我需要展示一个特定的问题以及它的回答。通常情况下,我需要进行两个查询:

Question.objects.get(id=1)
Answer.objects.get(question_id=1)[:10]

我希望使用一个查询语句来检索所有内容。在MySQL中,它会是:

SELECT *
FROM Question JOIN Answer ON Question.id=Answer.question_id
WHERE Question.id=1
LIMIT 10

是否有办法通过Django的ORM来实现这一点?
在这种情况下,extra()有用吗?

4个回答

64

这正是 select_related() 的作用。唯一需要注意的是你必须从Answer模型开始,而非Question模型,但结果相同:

answers = Answer.objects.filter(question_id=1).select_related() 

现在每个答案对象都有一个预取的“question”属性,访问它不会再次命中数据库。


2
谢谢,如果我们需要相关表格外键的名称,假设表格A与B相关联,并且B与C相关联。(所有表格只有“名称”和“ID”)。我们想要连接每个A的条目,并将其显示在相关的C表对象旁边。 - Bheid
28
如果question_id只是一个整数,并且Answer没有提供到Questionmodels.ForeignKey字段,那么这怎么能起作用呢? - Kurt Bourbaki

48
考虑使用models.ForeignKey(Question)代替question_id = IntegerField()
这是表达你试图描绘的问题和答案之间关系的最佳(更关联)方式。
这样,您只需调用Answers.objects.filter(question_id=<id>)即可获得所需内容。

使用 ForeignKey 确实是正确的方法,但是此答案提供的查询调用仅返回 Answer 对象,而问题是如何在一个查询中获取 QuestionAnswer 对象。 - talz

15
    class Question(models.Model):
      title = models.CharField(max_length=70)
      details = models.TextField()

    class Answer(models.Model):
      question = models.ForeignKey('Question')
      details = models.TextField()

    id = <whatever_id>    
    answers = Question.objects.get(id=id).answer_set.all()

“id”现在是一个内置函数,可能在2015年还不是。 - Shmack

4

#考虑图书和出版商之间的外键关系

class Publisher(models.Model):
 name = models.CharField(max_length=100)

eclass Book(models.Model):
 publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

#获取书籍的出版社名称

book = Book.objects.select_related('publisher').get(id=1)
book.publisher.name

#获取特定出版社出版的书籍

publisher = Publisher.objects.prefetch_related('book_set').get(id=1)
books = publisher.book_set.all()

更多信息请查阅https://kwikl3arn.com/django/JOINS


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接