2012-09-29 18 views
11

Me gustaría recuperar un montón de filas de mi base de datos usando un conjunto de filtros.django filtrando condicionalmente objetos

Me preguntaba si el filtro condicional es aplicable en django. Es decir, "filtrar si la variable no es Ninguna o no aplicar filtro de lo contrario".

Algo como esto:

user = User.objects.get(pk=1) 
category = Category.objects.get(pk=1) 
todays_items = Item.objects.filter(user=user, date=now()).conditional_filter(category=category)) 

Lo que me gustaría hacer es aplicar el filtro categoría sólo si la categoría no es Ninguno.

Si la categoría es Ninguna (significa que no se proporciona en el objeto de solicitud), entonces este filtro no se aplicará en absoluto. Esto me ahorraría un montón de situaciones 'if-elif-else'.

¿Hay alguna manera de hacerlo?

Respuesta

15

Se pueden ingresar las consultas de la cadena:

user = User.objects.get(pk=1) 
category = Category.objects.get(pk=1) 
qs = Item.objects.filter(user=user, date=now()) 
if category: 
    qs = qs.filter(category=category) 

Como queryset se ejecutan con pereza, DB éxito será sólo se producen cuando la presentación de los elementos.

2

Son varios los enfoques a su problema. Un método consiste en jugar con Complex lookups with Q objects

from django.db.models import Q 

user = User.objects.get(pk=1) 
category = Category.objects.get(pk=1) 

f1 = Q(user=user, date=now()) 
f_cat_is_none = Q(category__isnull = True) 
f_cat_is_not_none = Q(category=category) 

todays_items = Item.objects.filter(f1 & (f_cat_is_none | f_cat_is_not_none)) 

No entiendo la derecha en su respuesta si esta es la consulta que se está buscando, pero, con este ejemplo, usted puede componer fácilmente su propia consulta.

Editado comentario debido OP

category__isnull == True significa que, en la base de datos, el artículo no tiene una categoría asociada. Quizás la consulta que se está buscando es:

from django.db.models import Q 

user_pk = 1 
category_pk = 1 #some times None 

f = Q(user__pk = user_pk, date=now()) 
if category_pk is not None: 
    f &= Q(category__pk = category_pk) 

todays_items = Item.objects.filter(f ) 

Esto es sólo un ejemplo de código, se ajusta mejor a sus requerimientos. Tenga cuidado con solo _ y doble __.

+0

Gracias, lo que no entiendo es 'category__isnull = True'. Ninguno de mis objetos tiene NULL en su campo de categoría. Lo cual hace que sea siempre falso. – xpanta

+0

@xpanta, explicado en la respuesta. – danihp

+0

@danihp, lo siento, todavía no entiendo muy bien el __isnull = Verdadero. Se aplica a esta situación: un formulario que contiene "categoría", el usuario llena y envía el formulario. Si el usuario no ingresa "categoría", entonces este es "" para este valor. Luego, filtra la base de datos SIN la restricción de "categoría" si sigo tu primer ejemplo? Por favor corrígeme si mi comprensión es correcta. Gracias por adelantado. –

4

Bueno, esto es más bien cuestión de edad, pero para aquellos que quieran hacer el filtrado condicional en una línea, aquí está mi enfoque (Por cierto, el código siguiente puede probablemente ser escrito de una manera más genérica):

from django.db.models import Q 

def conditional_category_filter(category): 
    if category != None: 
     return Q(category=category) 
    else: 
     return Q() #Dummy filter 

user = User.objects.get(pk=1) 
category = Category.objects.get(pk=1) 
todays_items = Item.objects.filter(conditional_category_filter(category), user=user, date=now()) 

Lo único que necesita ver es usar la llamada conditional_category_filter(category) antes de los argumentos de la palabra clave como user=user. Por ejemplo, el siguiente código arrojaría un error:

todays_items = Item.objects.filter(user=user, date=now(), conditional_category_filter(category)) 
Cuestiones relacionadas