40 votes

Django : Requête de filtre basée sur une fonction personnalisée

J'ai une fonction intégrée dans ma classe de modèle Django et je souhaite utiliser cette fonction pour filtrer les résultats de ma requête.

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

Maintenant, je veux utiliser cette fonction dans mon filtre de requête, quelque chose comme

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

Je sais, pour ce cas simple 'is_active', je peux directement faire cette comparaison dans une requête de filtre, mais pour des situations plus complexes, cela peut ne pas être possible. Comment dois-je faire une requête, basée sur des fonctions personnalisées ?

27voto

Walter Renner Points 31

Je viens d'avoir un problème similaire. Le problème était que je devais retourner une instance QuerySet. Une solution rapide pour moi était de faire quelque chose comme:

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

Je suis sûr que ce n'est pas la façon la plus jolie et la plus performante de le faire, mais je travaille pour moi.

une façon plus détaillée de le faire serait :

 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)

19voto

Lapin-Blanc Points 597

Je vous suggère d'utiliser un gestionnaire personnalisé pour votre classe, comme celui-ci que vous pourriez utiliser :

nserv = service.objects.are_active()

Ceci serait réalisé avec quelque chose comme:

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

Voir les gestionnaires personnalisés

17voto

Vous ne pourrez peut-être pas, à la place, vous pouvez post-traiter le jeu de requêtes avec une compréhension de liste ou une expression génératrice .

Par example:

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

9voto

jeckyll2hide Points 4560

La réponse d'Ignacio est intéressante, mais elle ne renvoie pas de jeu de requêtes. Celui-ci fait :

 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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X