扩展过滤器功能以仅在变量具有值时使用

Extend Filter functionality to use only if variable have value

我正在使用 django 框架制作博客应用程序。 我的 Django 版本是 Django version 4.0.4

我应该根据博客的标题和类别过滤数据 我的代码如下

searchTitle = request.GET.get('searchTitle')
searchCat = request.GET.get('searchCat', '')

if searchTitle or searchCat:
    blogs = Blog.objects.filter(blog_title__icontains=searchTitle).order_by('-blog_id')
    if searchCat:
        blogs = Blog.objects.filter(blog_title__icontains=searchTitle,blog_category=searchCat).order_by('-blog_id')
else:
    blogs = Blog.objects.all().order_by('-blog_id')

这是完美的,但这没有意义,因为它不遵循 DRY principle

这里我为了搜索写了两遍Blog.object.filter代码。所以如果可能的话,我想尽量减少一行中的那个和那个问题。 那么你们可以指导我吗

您可以使用字典减少它

searchTitle = request.GET.get('searchTitle')
searchCat = request.GET.get('searchCat', '')

d = {}

if searchTitle or searchCat:
    d.update({"blog_title__icontains": searchTitle})
    if searchCat:
        d.update({"blog_category": searchCat})
if d:
    Blog.objects.filter(**d).order_by("-blog_id")
else:
    blogs = Blog.objects.all().order_by('-blog_id')

这很简单,但是单行是不可读的。 .filter不发送查询,所以操作可以一个一个添加。简单的 ifs 和几行代码使它成为您在这里可以获得的最易读的形式:

search_title = request.GET.get('searchTitle')
search_cat = request.GET.get('searchCat', '')

blogs = Blog.objects.all().order_by('-blog_id')  # no query sent to db

if search_title:
    blogs = blogs.filter(blog_title__icontains=search_title)  # no query sent

if search_cat:
    blogs = blogs.filter(blog_category=search_cat)  # no query sent

blog_ids = [blog.id for blog in blog]  # single query sent here

oneliner,将是这个(因为 icontains returns 所有对象中的空字符串 "" 参数):

search_title = request.GET.get('searchTitle', '')
search_cat = request.GET.get('searchCat', '')

blogs = Blog.objects.filter(
    blog_title__icontains=search_title,
    blog_category=search_cat,
).order_by('-blog_id')

注意:我已经更改了名称,因为Python中的驼峰式是为class名称保留的,变量应该使用snake_case。无论如何,这就是惯例。