当参数数量可能发生变化时,如何编写 OR 查询?
Posted
技术标签:
【中文标题】当参数数量可能发生变化时,如何编写 OR 查询?【英文标题】:How to write a OR query when number of parameters may change? 【发布时间】:2019-10-21 07:58:33 【问题描述】:我需要制作一个过滤器来显示具有以下条件的 BookInstances:
BookInstance.public = True
BookInstance.owner != current logged in user
BookInstance.book.title.icontains('some text')
BookInstance.book.description.icontains('some text')
BookInstance.book.authors(id_in=some list of ids)
BookInstance.book.categories(id_in=some list of ids)
条件将组合为:
1 AND 2 AND ( ( 3 OR 4 ) OR 5 OR 6 )
3 和 4 使用相同的文本进行搜索。
当前脚手架视图:
searchedObjects = BookInstance.objects.filter(public=True)
if request.user.is_authenticated:
searchedObjects = searchedObjects.exclude(owner=request.user)
filterObj = dict(request.POST)
for key in filterObj:
if key == 'bookTitleOrDescription':
#condition 3 & 4
bookTitleOrDescription = filterObj[key][0]
elif key == 'author[]':
#condition 5
authorList = filterObj[key]
elif key == 'category[]':
#condition 6
categoryList = filterObj[key]
searchedObjects
会有查询结果。
if, elif
是必需的,因为某些参数可能存在也可能不存在。我们必须避免为它写 10 个组合。
型号:
class Author(SafeDeleteModel):
name = models.CharField(max_length=255)
class Category(SafeDeleteModel):
title = models.CharField(max_length=255)
class Book(SafeDeleteModel):
title = models.CharField(max_length=255)
description = models.CharField(max_length=255)
authors = models.ManyToManyField(Author)
categories = models.ManyToManyField(Category)
class BookInstance(SafeDeleteModel):
owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
public = models.BooleanField(verbose_name='Will show in search ?')
lendable = models.BooleanField(verbose_name='In good condition ?')
【问题讨论】:
请阅读相关文档:docs.djangoproject.com/en/2.2/topics/db/queries。您已经写下了所有条件,您只需将其放入filter
。文档应该为您的所有案例提供答案;)
我读过那个过滤器和条件。问题在于 OR 条件。三者中的某些参数可能会丢失,然后需要在没有它们的情况下生成查询。我尽量避免写 10 个条件。
【参考方案1】:
您可以像这样过滤每个字段的查询:
author = request.POST.get('author', None)
if author:
searchedObjects = searchedObjects.filter(author=author)
【讨论】:
【参考方案2】:您可以通过以下方式进行:
filter = Q()
if key == 'category[]':
filter = filter | Q(book__category__id__in='some list of ids')
if key == 'author[]':
filter = filter | Q(book__authors__id__in='some list of ids')
....
....
data = BookInstance.objects.filter(filter)
【讨论】:
有时查询可能是这样的:(Q(title__icontains='some text') | Q(description__icontains='some text')) | Q(book__authors__id__in='some list of ids') | Q(book__category__id__in='some list of ids')
有时可能是这样 Q(book__authors__id__in='some list of ids') | Q(book__category__id__in='some list of ids')
OR 的所有三个参数可能不会一直存在。我已经相应地更新了问题。以上是关于当参数数量可能发生变化时,如何编写 OR 查询?的主要内容,如果未能解决你的问题,请参考以下文章
当嵌套字典键发生变化时,如何使用嵌套字典查询 mongodb 文档?
当 ref 随 vue 组合 api 发生变化时,如何触发 graphql 查询?