2012-09-29 36 views
11

Tôi muốn truy xuất một loạt các hàng từ cơ sở dữ liệu của tôi bằng cách sử dụng một bộ lọc.django điều kiện lọc đối tượng

Tôi đã tự hỏi nếu bộ lọc có điều kiện được áp dụng trong django. Tức là, "lọc nếu biến không phải là Không, hoặc không áp dụng lọc nếu không".

Something như thế này:

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

Những gì tôi muốn làm là áp dụng loại bộ lọc chỉ khi loại không phải là Không.

Nếu danh mục là Không (nghĩa là danh mục không được đưa ra trong đối tượng yêu cầu) thì bộ lọc này sẽ không được áp dụng. Điều này sẽ tiết kiệm cho tôi một loạt các tình huống 'if-elif-else'.

Có cách nào để thực hiện việc này không?

Trả lời

15

Bạn có thể chuỗi truy vấn:

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) 

Như queryset được thực hiện một cách lười biếng, DB hit sẽ chỉ xảy ra khi bạn hiển thị các mục.

2

Chúng là một số cách tiếp cận cho vấn đề của bạn. Một cách tiếp cận là để chơi với 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)) 

tôi không đúng hiểu trong câu trả lời của bạn nếu điều này là truy vấn mà bạn đang tìm kiếm, nhưng, với ví dụ này, bạn có thể soạn một cách dễ dàng truy vấn của riêng bạn.

Edited OP do bình luận

category__isnull == True có nghĩa là, trong cơ sở dữ liệu, mục không có một thể loại có liên quan. Có lẽ truy vấn bạn đang tìm kiếm là:

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 ) 

Đây chỉ là mẫu mã, phù hợp với yêu cầu của bạn. Hãy cẩn thận với _ và tăng gấp đôi __.

+0

Cảm ơn, điều tôi không hiểu là 'category__isnull = True'. Không có đối tượng nào của tôi có NULL trong trường thể loại của chúng. Mà làm cho nó luôn luôn là sai. – xpanta

+0

@xpanta, giải thích câu trả lời. – danihp

+0

@danihp, xin lỗi tôi vẫn không hiểu rõ __isnull = True. Nó có áp dụng cho tình huống này hay không: một biểu mẫu có chứa "category", người dùng điền và gửi form. Nếu người dùng không nhập "category" thì đây là "" cho giá trị này. Sau đó, lọc cơ sở dữ liệu KHÔNG CÓ ràng buộc của "thể loại" nếu tôi làm theo ví dụ đầu tiên của bạn? Hãy sửa tôi nếu hiểu biết của tôi đúng. Cảm ơn trước. –

4

Vâng, đây là câu hỏi khá cũ nhưng đối với những người muốn làm việc lọc có điều kiện trên cùng một dòng, đây là cách tiếp cận của tôi (Btw, các mã sau đây có thể có thể được viết một cách chung chung hơn):

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()) 

Điều duy nhất bạn cần xem là sử dụng cuộc gọi conditional_category_filter(category) trước các đối số từ khóa như user=user. Ví dụ: mã sau sẽ ném một lỗi:

todays_items = Item.objects.filter(user=user, date=now(), conditional_category_filter(category)) 
Các vấn đề liên quan