如何使用别名在Django中进行多表连接

2024-04-26 09:17:39 发布

您现在位置:Python中文网/ 问答频道 /正文

好吧,我在理解Django的连接和别名方面有点困难。我在模型中定义了四个表:(我删除了不相关的列)

class Field(models.Model):
    name = models.CharField(max_length=200, default='')

class Survey(models.Model):
    name = models.CharField(max_length=200, default='')

class Question(models.Model):
    text = models.CharField(max_length=200, default='')
    survey = models.ForeignKey(Survey)

class Answer(models.Model):
    question = models.ForeignKey(Question)
    field = models.ForeignKey(Field)

现在我可以编写一个非常简单易懂的sql查询来获得我想要的。看起来是这样的:

SELECT s.id, s.name, 
  q.id as q_id, q.text, 
  f.id as f_id, f.name as answer  
FROM "App_survey" s 
JOIN "App_question" q 
  ON q.survey_id = s.id
JOIN "App_answer" a 
  ON a.question_id = q.id 
JOIN "App_field" f 
  ON a.field_id = f.id;

但我一辈子都搞不懂如何使用orm来实现这一点。我甚至不能连接两个表并从中选择数据,更不用说处理别名了。就我所知:

questions = Question.objects.prefetch_related('survey')
questions_dict = [{'form':x.name, 'id':x.id, 'question':x.text} for x in questions]

这给了我一个'Question'对象没有'name'属性的错误。你知道吗

注意:这是postgres和python,我对这两个都不熟悉。你知道吗

更新:这是我使用的最后一个代码:

answers = Answer.objects.annotate(
    s_id=F('question__survey__id'),
    s_name=F('question__survey__name'),
    q_id=F('question__id'),
    text=F('question__text'),
    f_id=F('field__id'),
    answer=F('field__name')
)

surveys_dict = [{
    'id': x.s_id,
    'name':x.s_name,
    'q_id':x.q_id,
    'text':x.text,
    'f_id':x.f_id,
    'answer':x.answer
} for x in answers]

多亏了两位回答者,他们才有启发性。你知道吗


Tags: textanswernameidappfieldmodelmodels
2条回答

当您有ManyToOne关系时,应该使用select_related(*fields)(这执行SQL JOINS)。你知道吗

questions = Question.objects.select_related('survey')
questions_dict = [{'form':x.survey.name, 'id':x.id, 'question':x.text} for x in questions]

我想,这就是你需要的。你知道吗

这不起作用的原因是Question没有name属性。.prefetch_related只会自动填充相关模型。你知道吗

您可以做的是注释Question对象,例如:

from django.db.models import F

Question.objects.annotate(
    answer_text=F('answer__field__name'),
    s_name=F('survey__name')
)

现在,这个QuerySet中的Question将有两个额外的字段answer_texts_name,其中name是相关AnswerField,而s_nameSurvey的名称。你知道吗

相关问题 更多 >