Как сделать многостоловое объединение в Django с псевдонимами - PullRequest
0 голосов
/ 31 мая 2019

Хорошо, у меня возникли проблемы с пониманием того, как Джанго присоединяется и алиасуется. У меня есть четыре таблицы, определенные как таковые в моих моделях: (я удалил ненужные столбцы)

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;

Но я не могу понять, как это сделать, используя форму. Я даже не могу соединить две таблицы и выбрать данные из обеих, не говоря уже о псевдонимах. Это насколько я получил:

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

Это дает мне объект «Вопрос», не имеющий атрибута «имя», ошибка.

Примечание: это 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]

благодаря обоим ответчикам, они были просветляющими.

Ответы [ 2 ]

2 голосов
/ 31 мая 2019

Причина, по которой это не работает, заключается в том, что у вас 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')
)

Теперь Question s из это QuerySet будет иметь два дополнительных поля answer_text и s_name с name из Field соответствующих Answer (s) и s_nameимя Survey.

2 голосов
/ 31 мая 2019

Вы должны использовать select_related(*fields), когда у вас есть отношения ManyToOne (Это выполняет SQL JOINS).

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

Я думаю, это то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...