2011-04-16 12 views
27

Tengo una función incorporada en mi clase de modelo Django y quiero usar esa función para filtrar los resultados de mi consulta.Django: consulta de filtro basada en la función personalizada

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

Ahora quiero utilizar esta función en mi filtro de consulta, algo así como

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

que sé, en este caso sencillo 'is_active', puedo directamente hacer esta comparación en la consulta de filtro, pero para situaciones más complejas, eso puede no ser posible. ¿Cómo debería hacer una consulta, basada en funciones personalizadas?

+3

Por cierto, se puede hacer 'volver datetime.now() <= self.end_time' :-) – Rikki

+0

que tenían exactamente el mismo problema! Incluso la función se llamaba igual –

Respuesta

17

Yo te sugeriría utilizar un gestor personalizado para su clase, como esto puede usar:

nserv = service.objects.are_active()

Esto se lograría con algo como:

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

Ver custom managers

+20

'# use su método para filtrar resultados' es más o menos lo que la pregunta es cómo hacerlo hacer. –

+0

@Ignacio - En realidad, esta solución también me conviene. Así que iré con eso solo por probar algo diferente. – Neo

16

Es posible que no pueda, en su lugar puede post-procesar el conjunto de preguntas con un list comprehension o generator expression.

Por ejemplo:

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

¿Qué es LC/genex? – Neo

+6

LC = [lista de comprensión] (http://docs.python.org/tutorial/datastructures.html#list-comprehensions). genex = [expression generator] (http://docs.python.org/reference/expressions.html#generator-expressions) –

+0

@A lee -: P Todavía no me he acostumbrado a la jerga de Python. – Neo

13

Acabo de tener un problema similar. El problema fue que tuve que devolver una instancia de QuerySet. Una solución rápida para mí era hacer algo como:

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

bastante seguro de que esto no es la forma más bonita y performante para hacer esto, pero funciona para mí.

una manera más prolija de hacer esto sería:

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) 
+0

Gracias, esto es perfecto. Aún no es una función de django "cargar los resultados" y filtrar por el lado del cliente, por lo que esta es la única forma. – beiller

4

La respuesta de Ignacio es interesante, pero no devuelve un conjunto de consultas. Esto se hace:

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) 
Cuestiones relacionadas