2009-05-27 21 views
5

'入力された'モデルはdatetimeフィールドです。私は正午(start_time)と午後5時(end_time)の間に作られたすべてのエントリを見つけるためにデータを照会したい。日付時刻フィールドで時間をフィルタリングするにはどうすればよいですか?

selected = Entry.objects.filter(entered__gte=start_time, entered__lte=end_time) 

(私は期待通りに)私はのエラーを取得する:

"ValidationError: Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format." 

だから私は、私は私が試した__year使用することができます知っています。

selected = Entry.objects.filter(entered__time__gte=start_time, entered__time__lte=end_time) 

私はエラーを取得:私はそこに内蔵されています。このためのサポートとは思わないが、あなたはextra where-clauseパラメータ(警告渡すことができます

"FieldError: Join on field 'start' not permitted. Did you misspell 'time' for the lookup type?" 

答えて

2

あなたは、DBのメカニズムを使用して、代わりにPythonでフィルタリングすることができます:

for e in Entry.objects.all(): 
    if i.entered.hour>= 9 and i.entered.hour < 17 :# or break down to minutes/seconds 
     list.append(e) 

しかし、両方の解決策は醜いと思います。

スティーブ、あなたはあなたのためのあまり醜いあるか、を判断する必要があります。

、forループ、
  • または.extra使用中に大量のデータをprocesssing
    • (..)とすることにより、通過オームシステム
  • +0

    これは私が好む選択です。私はまだもっと良い選択肢を望んでいます。 –

    +2

    django 1.8で時/分をフィルタリングすることが可能です: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#hour Entry.objects.filter(入力_hour__gte = 9、入力_hour__lte = 17) – imposeren

    +0

    残念ながら、Django 1.8では不可能です。あなたは正確な時間の一致をフィルタリングすることができます: 'Entry.objects.filter(entered__hour = 9) ' –

    5

    :DBに依存する動作を導入するいくつかの可能性をここに)。

    例えば、Postgresの、のようなもので:

    Entry.objects.extra(where=['EXTRACT(hour from entered) >= 12 and '\ 
            'EXTRACT(hour from entered) < 17']) 
    

    あなたが値1217を決定するために、潜在的に危険な入力を使用している場合、あなたも保証します余分にのparamsオプションを指定することができることに注意してください適切な引用とエスケープを行い、where文に標準のSQL %sプレースホルダを使用します。

    +1

    私はこれらの線に沿って何かを投稿するちょうど約ました。 SQLiteを使うと、 'Entry.objects.extra(ここで= ["12:00"と "17:00" "]の間の時間(入力))は同じことをするはずです。 – Arnaud

    +0

    もちろん、カスタムSQLを使わないで時間範囲を尋ねることができます。私の答えを参照してください – vikingosegundo

    0

    end_timeにはdatetime objectsを指定しましたか?

    迅速試しアウト:

    例としてSQLiteのを使用して
    class Entry(models.Model): 
        entered = models.DateTimeField() 
    
    >>> from datetime import datetime 
    >>> Entry(entered = datetime.now()).save() 
    >>> Entry.objects.filter(entered__lte = datetime.now()) 
    [<Entry: Entry object>] 
    >>> Entry.objects.filter(entered__gte = datetime.now()) 
    [] 
    >>> Entry.objects.filter(entered__gte = datetime.now(), entered__lte=datetime(2009,11,1,0,0)) 
    [<Entry: Entry object>] 
    
    +1

    はい、あなたは本当に質問に答えるわけではありません:それは午後12時から午後7時の間に作られたすべてのエントリを返すことになっています。 – Arnaud

    +1

    そして、時間が12時34分54秒から14時23分6秒までしかフィルタリングしたくない場合、重要なことはフィルタが日付ではなく時間を考慮することです。 –

    +0

    'extra()'修飾子を使うのは唯一のオプションだと思います。スティーブン、どのDBバックエンドを使用していますか? – Arnaud

    3

    、比較的きれいで、一般的な解決策は次のようになります。

    Entry.objects.extra(where=["time(entered) between '%s' and '%s'"], 
            params=[start_time.strftime("%H:%M"), end_time.strftime("%H:%M")]) 
    
    +0

    この解決法には小さなバグがあり、30分苦労しました。あなたは '%s'を引用符で囲む必要はないので、%sから% ""。それ以外に、 'extra()'は現在廃止されており、[RawSql](https://docs.djangoproject.com/ja/1.8/ref/models/expressions/)を使って提案しています。 #django.db.models.expressions.RawSQL)。 –

    0

    フィルタx<=argを除き、x>=arg2を除きます。

    -2

    範囲を使用してフィルタリングすることができます。 SQLがDjangoよりも優れたフィルタリングを行うので、これをフィルタリングする最良の方法が見つかりました。

    fromRange=datetime.datetime.strptime(request.GET.get('from'),'%Y-%m-%dT%H:%M:%S.%fZ') 
    toRange=datetime.datetime.strptime(request.GET.get('to'),'%Y-%m-%dT%H:%M:%S.%fZ') 
    
    entry = Entry.objects.filter(entryTime__range=(fromRange,toRange)) 
    
    0

    私は同様のユースケースのためのソリューションを考え出した - おそらく誰かが、これは重宝:

    私の場合、私は(簡体字)そうのような可用性と制約のモデルを持っている:

    class Availability(...): 
        start = models.DateTimeField() 
        end = models.DateTimeField() 
    
    class Constraint(...): 
        from = models.TimeField() 
        to = models.TimeField() 
    

    私はどんな制約にも違反しない可用性を見つけたかったのです。 ::timeであなたは(Postgresの用語でいうかtimestamptime without timezoneに)DateTimeからTimeキャストすることができますどのように

    ​​

    注意をして、時間範囲を比較するOVERLAPSを使用します。Postgresので

    が、これは私のために働きました。

    そして、元の質問に関しては、あなたも行うことができます。

    Availability.objects.extra(
        where=['start::time BETWEEN \'{0}\'::time AND \'{1}\'::time AND 
          "end"::time BETWEEN \'{0}\'::time AND \'{1}\'::time'.format(
         from.strftime("%H:%M"), to.strftime("%H:%M") 
        )] 
    ) 
    
    関連する問題