@Welltraum
Инженер-конструктор

Как сделать выборку из нескольких таблиц с помощью Django ORM?

Добрый день. Изучаю потихоньку django. Создал следующую модель сотрудников, должностей и связи между ними:
from django.utils import timezone
class Person(models.Model):
    last_name = models.CharField(max_length=50, help_text=u'Фамилия сотрудника', verbose_name=u'Фамилия')
    first_name = models.CharField(max_length=50, help_text=u'Имя сотрудника', verbose_name=u'Имя')
    patronymic = models.CharField(max_length=50, help_text=u'Отчество сотрудника', verbose_name=u'Отчество')

class Position(models.Model):
    position_name = models.CharField(max_length=200, help_text=u'Должность', verbose_name=u'Должность')

class Transfer(models.Model):
    """ В таблице храним даты переводов на новые должности """
    person = models.ForeignKey('structure_department.Person')
    new_position = models.ForeignKey('structure_department.Position')
    data_transfer = models.DateField(default=timezone.now, help_text=u'Дата перевода на новую должность', verbose_name=u'Дата')

Теперь пытаюсь во views создать список сотрудников с актуальными должностями на сегодняшний день:
def person_list1(request):
    persons = Transfer.objects.all().annotate(data=Max('data_transfer')).order_by('last_name')
    list_users = []
    for person in persons:
        max_data_transfer = Transfer.objects.filter(person=person).aggregate(max_data_transfer=Max('data_transfer'))['max_data_transfer']
        position = Transfer.objects.filter(person=person, data_transfer=max_data_transfer)[0].new_position
        list_users.append({'person': person, 'position': position})
    return render(request, 'structure_department/person_list.html', {'persons': persons})

Получилось сложно и некрасиво для тривиально задачи. Потом попробовал с помощью SQL запроса:
def person_list2(request):
    qwery = "SELECT t1.id, person.first_name, person.last_name, person.patronymic, pos.position_name, t1.data_transfer \
             FROM structure_department_transfer t1, \
                  structure_department_person person, \
                  structure_department_position pos \
             WHERE data_transfer = (SELECT MAX(data_transfer) \
                                    FROM structure_department_transfer t2 \
                                    WHERE t1.person_id = t2.person_id) \
             AND t1.person_id = person.id \
             AND t1.new_position_id = pos.id \
             GROUP BY person.last_name"
    persons = Transfer.objects.raw(qwery)
    return render(request, 'structure_department/person_list.html', {'persons': persons})

Получилось опять сложно. Поэтому прощу поделиться опытом, в следующих вопросах:
  1. Как правильно составить модель сотрудников, должностей и таблицы с информацией кого когда повышали?
  2. Как правильно составить запрос на Django ORM, что бы вывести список сотрудников со всеми актуальными должностями?
  • Вопрос задан
  • 3011 просмотров
Решения вопроса 1
winordie
@winordie
Лучшая документация -- исходники
Person.objects.order_by(
  'id', '-transfer__data_transfer').distinct('id').values_list(
  'last_name', 'transfer__new_position__position_name', 'transfer__data_transfer')
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
un1t
@un1t
1. По моделям вроде все нормально.

2. Как я понимаю основная проблема в том, чтобы получить актуальные записи в таблице transfers;
Это можно сделать таким образом
select * from (select * from transfers order by date desc) as t group by person_id

Ну и два джойна с таблицами persons и positions уже сам добавишь.
Ответ написан
@HunterBjj
structure_department_person что это????? перед таблицей
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы