web-dev-qa-db-ja.com

Django:カスタム関数に基づいてクエリをフィルターします

Djangoモデルクラスに組み込まれている関数があり、その関数を使用してクエリ結果をフィルター処理したいと考えています。

  class service:
       ......
       def is_active(self):
            if datetime.now() > self.end_time:
                  return False
            return True

次に、この関数をクエリフィルターに使用します。

nserv = service.objects.filter(is_active=True)

この単純な「is_active」の場合は、フィルタークエリで直接この比較を行うことができますが、より複雑な状況ではそれができない場合があります。カスタム関数に基づいて、クエリをどのように作成すればよいですか?

33
Neo

私はあなたがあなたが使うことができるこのように、あなたのクラスのためにカスタムマネージャーを使うことを勧めます:

nserv = service.objects.are_active()

これは次のようなもので達成されます:

class ServiceManager(models.Manager):
    def are_active(self):
        # use your method to filter results
        return you_custom_queryset

カスタムマネージャ を参照

18
Lapin-Blanc

同様の問題が発生しました。問題は、QuerySetインスタンスを返さなければならないことでした。私のための簡単な解決策は、次のようなことをすることでした:

active_serv_ids = [service.id for service in Service.objects.all() if service.is_active()]
nserv = Service.objects.filter(id__in=active_serv_ids)

これがこれを行うには最もきれいでパフォーマンスの高い方法ではないことを確信していますが、私は私のために働いています。

これを行うより詳細な方法は次のとおりです。

active_serv_ids = []

for service in Service.objects.all():
if service.is_active():
    active_serv_ids.append(service.id)

nserv = Service.objects.filter(id__in=active_serv_ids)
16
Walter Renner

できない場合があります。代わりに、クエリセットを リスト内包表記 または ジェネレータ式 で後処理できます。

例えば:

[x for x in Q if x.somecond()]

Ignacioの回答は興味深いですが、クエリセットを返しません。これは:

def users_by_role(role):
    users = User.objects.all()
    ids = [user.id for user in users if user.role == role]
    return users.filter(id__in=ids)
4
dangonfast