2016-10-13 11 views
1

I'vはかなり長い間検索されていますが、sofに関するいくつかの解答について知っていますが、問題が非常に単純であっても、Django - datetimeフィールドから日付/日で区切られた別個の行/オブジェクト

私が必要とするもの(postgres + django 1.10を使用して):私はdatetimeフィールド内に多くの重複した日付(=日)を持つ多くの行を持っています。私は1つの行/オブジェクト毎日/日を含むクエリセットが欲しい。

fk | col1 | colX | created (type: datetime) 
---------------------------------------------- 
1 | info | info | 2016-09-03 08:25:52.142617+00:00 <- get it (time does not matter) 
1 | info | info | 2016-09-03 16:26:52.142617+00:00 
2 | info | info | 2016-09-03 11:25:52.142617+00:00 
1 | info | info | 2016-09-14 16:26:52.142617+00:00 <- get it (time does not matter) 
3 | info | info | 2016-09-14 11:25:52.142617+00:00 
1 | info | info | 2016-09-25 23:25:52.142617+00:00 <- get it (time does not matter) 
1 | info | info | 2016-09-25 16:26:52.142617+00:00 
1 | info | info | 2016-09-25 11:25:52.142617+00:00 
2 | info | info | 2016-09-25 14:27:52.142617+00:00 
2 | info | info | 2016-09-25 16:26:52.142617+00:00 
3 | info | info | 2016-09-25 11:25:52.142617+00:00 
etc. 

これを行うには最高のパフォーマンス(pythionic/django)方法がありますか?私のモデル/テーブルには、多くの行(> 100万)があります。

EDIT 1

結果(例えばWHERE FK = 1)FKによってフィルタリングされなければなりません。

は、私はすでに、このような

MyModel.objects.filter(fk=1).order_by('created__date').di‌​stinct('created__dat‌​e') 

として最も明白なものを試してみましたが、次のエラーました:代わりに、クエリのクラスメタを通じて

django.core.exceptions.FieldError: Cannot resolve keyword 'date' into field. Join on 'created' not permitted.

...すべてと同じエラー()とそれぞれの順序を-method order_by()...

この特定のケースでは、誰かがこのエラーについてもっと知っているかもしれませんか?

答えて

0

あなたはpostgresqlを使用しているため、Querysetを使用してテーブルから結果を得ることができます。私はあなたのDjangoあまりにもクエリセットのマニュアルを参照してください

MyModel.objects.all().distinct('created__date') 

はたぶん、このようなクエリが作業を行う必要がありますhttps://docs.djangoproject.com/fr/1.10/ref/models/querysets/#distinct

+0

これがうまくいくと思いますが、それは '.distinct( 'created__date')'ではないでしょうか? –

+0

ええ、そうです、ポストでは「時間は問題ではない」とは見えませんでした。回答が編集されました。 –

+0

...これは、次のエラーで試してみると、もっとも明白な解決策の1つです: – Schmalitz

0

私は同様の問題に遭遇した - ないorder_by()またはdistinct()と、 filter()となります。私はDjango 1.9を使用していますが、ここでは違いはありません。

私のアプリケーションの1つのモデルでは、filter(datetime_field__date__lt=(date(2016, 12, 5)))は問題なく、同じプロジェクト内の別のアプリケーションの別のモデルでも同じエラーが表示されます。

私の場合は、django-moneyhttps://github.com/django-money/django-money)で問題が発生しているようです。私が今まで知る限り、の機能はdjmoney.models.managersから__dateルックアップ(https://docs.djangoproject.com/en/1.9/ref/models/querysets/#date)を破ります。

私はmoney_manager()でそれをラップすることなく、関連するモデルに、たとえばtestmanager = models.Manager()ためobjects名前が付けられていない別のマネージャを、添付すると、__date検索は、モデルやデータベースへのその他の変更を加えることなく、再び正常に動作します。

私は完全に満足のいく解決策を見つけられませんでしたが、デフォルトマネージャで回り込んでいるdjango-moneyまたは別のサードパーティアプリケーションも使用していますか?たぶんトレースバックは、どのパッケージが問題であるかについてのヒントを示します。 Traceback (most recent call last): File "<input>", line 1, in <module> File "/[...]/python3.4/site-packages/django/db/models/manager.py", line 122, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/[...]/python3.4/site-packages/djmoney/models/managers.py", line 164, in wrapper args, kwargs = _expand_money_kwargs(model, args, kwargs, exclusions) File "/[...]/python3.4/site-packages/djmoney/models/managers.py", line 136, in _expand_money_kwargs elif isinstance(_get_field(model, name), MoneyField): File "/[...]/python3.4/site-packages/djmoney/models/managers.py", line 63, in _get_field field = qs.setup_joins(parts, opts, alias)[0] File "/[...]/python3.4/site-packages/django/db/models/sql/query.py", line 1405, in setup_joins names, opts, allow_many, fail_on_missing=True) File "/[...]/python3.4/site-packages/django/db/models/sql/query.py", line 1373, in names_to_path " not permitted." % (names[pos + 1], name)) django.core.exceptions.FieldError: Cannot resolve keyword 'date' into field. Join on 'my_datetime_field' not permitted.

+0

Fyi - 私が 'django-money'で経験した問題は本当にバグだったので、すでにマスターブランチで修正されています:https://github.com/django-money/django-money/issues/241 – goetz

0

これが(Postgres window functionsのように)高度なDBのバックエンド機能を使用することを含むと同じように、現在のDjangoの実装で与えられた可能ではないようです。

私のトレースバックは、このようになります。

あなたが持っている最も近いものは、集計を使用することです:

MyModel.objects.annotate(
    created_date=TruncDay('created') 
).values('created_date').annotate(id=Min('id')) 

これは、類似した日数を超える集約、およびピックアップ最小限のIDをでしょう。

[{'created_date': datetime.date(2017, 3, 16), 'id': 146}, 
{'created_date': datetime.date(2017, 3, 28), 'id': 188}, 
{'created_date': datetime.date(2017, 3, 24), 'id': 178}, 
{'created_date': datetime.date(2017, 3, 23), 'id': 171}, 
{'created_date': datetime.date(2017, 3, 22), 'id': 157}] ... 

あなたが全体のオブジェクトが必要な場合は、.values_list()とチェーンにこれをし、サブクエリにつながる別のクエリセット、することができます:FYI、これは次のクエリ

MyModel.objects.filter(
    id__in=MyModel.objects.annotate(
     created_date=TruncDay('created') 
    ).values('created_date').annotate(id=Min('id')).values_list(
     'id', flat=True 
    ) 
) 

結果

SELECT 
    "myapp_mymodel"."id", 
    "myapp_mymodel"."created", 
    "myapp_mymodel"."col1", 
    "myapp_mymodel"."colX" 
FROM "myapp_mymodel" 
WHERE "myapp_mymodel"."id" IN (
    SELECT MIN(U0."id") AS "id" 
    FROM "myapp_mymodel" U0 
    GROUP BY DATE(U0."created") 
) 
関連する問題