0

タイトルに意味があるかどうかはわかりませんが、ここで質問です。

コンテキスト: どの生徒が教室に出入りするかを追跡して、いつでも誰が教室にいるかを知ることができるようにしたいと考えています。また、生徒が教室に何回入ったかなどを追跡したいと考えています。これは、私が達成したいことに非常に近い架空の例です。

テーブル Classroom を作成し、各エントリには Student (ForeignKey)、Action (enter、leave)、および Date があります。

私の質問は、現在中にいる学生を取得する方法 (つまり、入力アクションの日付が退出アクションの日付よりも遅い、または退出日がない)、および日付範囲を指定して学生を取得する方法です。当時教室にあったもの。


編集:よく考えて、複数の教室があることも追加する必要があります.

私の最初の試みは次のようなものでした:

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_now2 つの「enters」と 1 つの「leave」があるため、彼女はクエリセットに 2 回リストされています。また、特定の日付範囲を調べて、入学日が退学日より後の生徒を確認することもできません。

4

2 に答える 2

1

Django はQ()andF()演算子を提供します。これは非常に強力で、ほとんどの状況に十分対応できます。しかし、それはあなたにとって十分ではないと思います。あなたの問題を 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 コードを記述し、Django で生の SQLを使用することをお勧めするということです。

より一般的なデータ アクセス API を使用する必要がある場合は、@Daniel Rosemanが示唆する方法でデータ モデルを書き直す必要があります。

ちなみに、同じ間隔で教室にいた人を取得するクエリはそれと同じですが、最後のleave tsを間隔の最初に、最後のenter tsを最後に制限するだけで済みます。間隔の。

于 2010-01-23T00:14:34.727 に答える
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)
于 2010-01-22T16:32:32.047 に答える