当参数数量可能发生变化时,如何编写 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 查询?的主要内容,如果未能解决你的问题,请参考以下文章

当变量发生变化时,Apollo 客户端缓存不会在查询中更新

当嵌套字典键发生变化时,如何使用嵌套字典查询 mongodb 文档?

当 ref 随 vue 组合 api 发生变化时,如何触发 graphql 查询?

当单元格可能发生变化时,Powershell excel合并单元格

当 vuex 商店的值发生变化时,如何更新组件中的状态?

spss非线性回归