2010-01-22 2 views
0

Я не уверен, имеет ли смысл смысл, но вот вопрос.Получение уникальных результатов в Django queryset на основе содержимого столбца

Контекст: Я хочу отслеживать, какие ученики входят и покидают класс, чтобы в любой момент я мог знать, кто находится внутри класса. Я также хочу отслеживать, например, сколько раз студент вошел в класс. Это гипотетический пример, который очень близок к тому, чего я хочу достичь.

Я сделал таблицу Classroom, и каждая запись имеет Student (ForeignKey), Action (введите, оставить) и Date.

Мой вопрос заключается в том, как получить учащиеся, которые в настоящее время находятся внутри (то есть дата их вступления в действие, более поздняя, ​​чем дата их отпуска или дата отпуска), и как указать диапазон дат чтобы получить учеников, которые были в классе в то время.


Edit: На лучшей мысли я хотел бы также добавить, что есть более чем один классы.

моя первая попытка была что-то вроде этого:

students_in = Classroom.objects.filter(classroom__exact=1, action__exact='1') 
students_out = Classroom.objects.filter(classroom__exact=1, action__exact='0').values_list('student', flat=True) 
students_now = students_in.exclude(student__in=students_out) 

где, если action == 1 в, 0 выходит.

Это, однако, дает неверные данные, как только студент покидает класс и снова входит. Она указана дважды в запросе students_now, так как есть два «входа» и один «отпуск». Кроме того, я не могу проверить конкретные диапазоны дат, чтобы узнать, какие студенты имеют дату записи, которая позже даты отпуска.

ответ

1

Для проверки поля по значению другого поля используйте команду F().

from django.db.models import F 
students_in_classroom_now = Student.objects.filter(leave__gte=F('enter')) 

Для получения всех студентов в комнате в определенное время:

import datetime 
start_time = datetime.datetime(2010, 1, 21, 10, 0, 0) # 10am yesterday 
students_in_classroom_then = Student.objects.filter(enter__lte=start_time, 
                leave__gte=start_time) 
+0

спасибо, я проверю его и дам вам знать. поэтому вместо того, чтобы иметь один столбец для действия, вы предлагаете наличие двух столбцов (введите и оставьте). в таком случае, в админе, как я могу убедиться, что хотя бы один не является нулевым. –

1

Джанго дает вам Q() и F() операторов, которые являются очень мощными и достаточно для большинства ситуаций. Однако я не думаю, что этого вам будет достаточно. Давайте рассмотрим вашу проблему на уровне SQL.

У нас есть что-то вроде стола Classroom (action, ts, student_id). Для того, чтобы знать, какие студенты в классе прямо сейчас, мы должны сделать что-то вроде:

with (/* temporary view with last user_action */ 
    select action, max(ts) xts, student_id 
    from Classroom 
    group by action, student_id 
) as uber_table 
select a.student_id student_id 
from uber_table a, uber_table b 
where a.action = 'enter' 
    /* either he entered and never left */ 
    and (a.student_id not in (select student_id from uber_table where action = 'leave') 
    /* or he left before he entered again, so he's still in */ 
    or (a.student_id = b.student_id and b.action = 'leave' and b.xts < a.xts)) 

Это, я думаю, стандартный SQL. Тем не менее, если вы используете SQLite или MySQL как базы данных бэкэндов (скорее всего, вы есть), то такие вещи, как ключевое слово WITH для создания временных просмотров, вероятно, не поддерживаются, и запрос просто должен стать еще более сложным , Там может быть более простая версия, но я ее не вижу.

Суть в том, что, когда вы дойдете до такого уровня сложности, F() и Q() становятся неадекватные инструменты для работы, так что я предпочел бы рекомендовать, чтобы писать код SQL вручную и использовать Raw SQL in Django.

Если вам нужно использовать более распространенные API доступа к данным, вероятно, вы должны переписать свою модель данных так: @ Daniel Roseman подразумевается.

Кстати, запрос на получение людей, которые были внутри класса в тот же промежуток, точно такой же, но все, что вам нужно сделать, это ограничить последнее оставить ts до начала интервала и последний введите ts до конца интервала.