フルスタックチャンネル
サインアップサインアップ
ログインログイン
利用規約プライバシーポリシーお問い合わせ
Copyright © All rights reserved | FullStackChannel
解決済
クエリセットの検索に、フィールド値ではなく関数の戻り値を使用したい
Django
Python
atnek
2022/08/14 15:33

実現したいこと

お世話になっております。
オブジェクトでフィルターを掛ける際に、モデルで定義した関数の戻り値を使用したいのですが、方法はありますでしょうか?

モデルには期限を設定しており、
その残存日数はステータスによって異なるので、下記のような関数を定義しています。

ソースコード

def remainingdays(self):
	if self.is_completed:
		return (self.completed_at + dt.timedelta(days=7) - timezone.make_aware(dt.datetime.now())).days
	if self.shipped_at:
		return (self.shipped_at + dt.timedelta(days=14) - timezone.make_aware(dt.datetime.now())).days
	if self.canceled_at:
		return (self.canceled_at + dt.timedelta(days=3) - timezone.make_aware(dt.datetime.now())).days
	if self.terminated_at:
		if self.status == 80:
			return (self.terminated_at + dt.timedelta(days=7) - timezone.make_aware(dt.datetime.now())).days
		if self.status == 90:
			return (self.terminated_at + dt.timedelta(days=3) - timezone.make_aware(dt.datetime.now())).days
	if self.flag:
		return (self.found_at + dt.timedelta(days=14) - timezone.make_aware(dt.datetime.now())).days
	if self.due_date:
		return	(self.due_date - dt.date.today()).days
	return 0

自分で試したこと

この戻り値を使って、filterをかけたいのですが、
色々と探し、labda等の方法を色々と試しましたが解決が出来ず。。。

お手数ですが、ご教示を頂ければ幸いです。

回答 4件
login
回答するにはログインが必要です
atnek
約3年前

ご回答ありがとうございます。

当初はQを用いて分岐をかけていたのですが、
上記のモデルメソッドには順位があり、ごちゃごちゃになっておりました。

カスタムマネージャーで下記のように定義したら、動作しました。
ありがとうございます!

def activeobjects(self):
	qs = self.get_queryset()
	ids = []
	for q in qs:
		if not q.remainingdays() > 0:
			ids.append(q.id)
	return qs.exclude(id__in=ids)

ちなみに、該当オブジェクト.objects.prefetch_related~と定義すると何も吐かなくなってしまうのですが、
カスタムマネージャーの場合、どこにprefetch_relatedを定義すれば良いのでしょうか?

それと、forで回してしまうと、数が増えたときに大丈夫かなーという懸念が、、、笑

1
atnek
約3年前

ですよねー
どこを調べても、カスタムマネージャーで動作しなくなるなんて書いてないのでおかしいなーと思いつつ。

return qs.select_related().exclude(id__in=ids)

上記のマネージャーでreturnのところに追加したら動作したので、ひとまず大丈夫になりました!
※qs = self.select_related().get_queryset()としても何故か駄目なのは無視して置きます。笑

1
はる@講師
約3年前

うまくいって良かったです。

カスタムマネージャーを使用していても、select_relatedもprefetch_relatedもfilterをする前に事前に取得する使い方は同じような気はします。

はる@講師
約3年前

カスタムマネージャーを使用するのはいかがでしょうか?

https://blog.narito.ninja/detail/105

1