DateTimeField
日付との比較をフィルタリングしようとしています。というのは:
MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))
私は時間を考慮していない(と思う)ため、空のクエリセットリストを回答として取得しますが、「いつでも」欲しいのです。
これを行う簡単な方法はDjangoにありますか?
設定された日時に時刻がありますが、そうではありません00:00
。
DateTimeField
日付との比較をフィルタリングしようとしています。というのは:
MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))
私は時間を考慮していない(と思う)ため、空のクエリセットリストを回答として取得しますが、「いつでも」欲しいのです。
これを行う簡単な方法はDjangoにありますか?
設定された日時に時刻がありますが、そうではありません00:00
。
回答:
このようなルックアップはdjango.views.generic.date_based
、次のように実装されます。
{'date_time_field__range': (datetime.datetime.combine(date, datetime.time.min),
datetime.datetime.combine(date, datetime.time.max))}
非常に冗長であるため、__date
演算子を使用して構文を改善する計画があります。詳細については、「#9596 DateTimeFieldと日付の比較は難しい」を確認してください。
Q(created__gte=datetime.combine(created_value, time.min))
Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
YourModel.objects.filter(datetime_published__year='2008',
datetime_published__month='03',
datetime_published__day='27')
//コメントの後に編集します
YourModel.objects.filter(datetime_published=datetime(2008, 03, 27))
時間値が0に設定されたdatetimeオブジェクトを作成し、データベース内の時間が一致しないため、機能しません。
ここに私がipythonのtimeit関数で得た結果があります:
from datetime import date
today = date.today()
timeit[Model.objects.filter(date_created__year=today.year, date_created__month=today.month, date_created__day=today.day)]
1000 loops, best of 3: 652 us per loop
timeit[Model.objects.filter(date_created__gte=today)]
1000 loops, best of 3: 631 us per loop
timeit[Model.objects.filter(date_created__startswith=today)]
1000 loops, best of 3: 541 us per loop
timeit[Model.objects.filter(date_created__contains=today)]
1000 loops, best of 3: 536 us per loop
含まれている方が速いようです。
contains
ソリューションを、私はエラーメッセージが表示されます:Unable to get repr for <class 'django.db.models.query.QuerySet'>
__contains
フィルターが原因でエラーが発生したとは思いません。しかし、問題が発生している場合は、を使用しているdjango docsの例を試してみてください__gte
。
startswith
ソリューション...
Djangoには、開発バージョンの日付に対してdatetimeオブジェクトをクエリする__date querysetフィルターがあります。したがって、1.9でまもなく利用可能になります。
これは、__ year、__ month、および__dayを使用した場合と同じ結果を生成し、私にとってはうまくいくようです:
YourModel.objects.filter(your_datetime_field__startswith=datetime.date(2009,8,22))
これは興味深い手法です。MySQLのDjangoで実装されたstartswithプロシージャを利用して、日付のみを介して日時のみを検索する結果を達成しました。基本的に、Djangoがデータベースでルックアップを行う場合は、DATETIME MySQLストレージオブジェクトの文字列変換を行う必要があるため、日付のタイムスタンプ部分を除外してフィルタリングできます。これにより、%LIKE%は日付のみに一致しますオブジェクトと指定した日付のすべてのタイムスタンプを取得します。
datetime_filter = datetime(2009, 8, 22)
MyObject.objects.filter(datetime_attr__startswith=datetime_filter.date())
これにより、次のクエリが実行されます。
SELECT (values) FROM myapp_my_object \
WHERE myapp_my_object.datetime_attr LIKE BINARY 2009-08-22%
この場合のLIKE BINARYは、タイムスタンプに関係なく、日付のすべてに一致します。以下のような値を含みます:
+---------------------+
| datetime_attr |
+---------------------+
| 2009-08-22 11:05:08 |
+---------------------+
うまくいけば、Djangoが解決策を発表するまで、これがすべての人に役立ちます!
これをカバーする素晴らしいブログポストがあります:Django ORMで日付と日付時刻を比較する
Django> 1.7、<1.9に投稿された最良のソリューションは、変換を登録することです:
from django.db import models
class MySQLDatetimeDate(models.Transform):
"""
This implements a custom SQL lookup when using `__date` with datetimes.
To enable filtering on datetimes that fall on a given date, import
this transform and register it with the DateTimeField.
"""
lookup_name = 'date'
def as_sql(self, compiler, connection):
lhs, params = compiler.compile(self.lhs)
return 'DATE({})'.format(lhs), params
@property
def output_field(self):
return models.DateField()
その後、次のようにフィルターで使用できます。
Foo.objects.filter(created_on__date=date)
編集
このソリューションは間違いなくバックエンドに依存しています。記事から:
もちろん、この実装は、DATE()関数を持つSQLの特定の種類に依存しています。MySQLにはあります。SQLiteも同様です。一方、私はPostgreSQLを個人的に操作したことはありませんが、グーグル操作を行うと、それがDATE()関数を持たないものと思われます。したがって、この単純な実装は、バックエンドに依存する必要があるようです。
return '{}::date'.format(lhs), params
Model.objects.filter(datetime__year=2011, datetime__month=2, datetime__day=30)
Django 1.7.6で動作します:
MyObject.objects.filter(datetime_attr__startswith=datetime.date(2009,8,22))
__lte
、たとえば使用できません。
Djangoのドキュメントを参照してください。
ur_data_model.objects.filter(ur_date_field__gte=datetime(2009, 8, 22), ur_date_field__lt=datetime(2009, 8, 23))