Django: implementing JOIN using Django ORM?

67,289

Solution 1

This is exactly what select_related() does. The only gotcha is that you have to start with the Answer model, rather than Question, but the result is the same:

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

Now each answer object has a pre-fetched 'question' attribute, and accessing it won't hit the db again.

Solution 2

Consider using models.ForeignKey(Question) instead of question_id = IntegerField().

This is the optimal (more relational) way to express the relationship between Questions and Answers you are trying to portray.

This way you can simply call Answers.objects.filter(question_id=<id>) and get exactly what you're looking for.

Solution 3

    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()
Share:
67,289
José Manuel Ramos
Author by

José Manuel Ramos

Updated on July 22, 2020

Comments

  • José Manuel Ramos
    José Manuel Ramos almost 4 years

    I have a Q&A type of site built in Django with the following models:

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

    I need to display a specific question together with its answers. Normally I'd need 2 queries to do that:

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

    I'm hoping to retrieve everything using one query. In MySQL it'd be:

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

    Is there anyway I could do this through Django's ORM? Would extra() help in this case?