Home > Enterprise >  Extend Filter functionality to use only if variable have value
Extend Filter functionality to use only if variable have value

Time:05-04

I am using the django framework for make an blog app. my django version is Django version 4.0.4

i am supposed to do filter the data as per Title And category that blog does have my code is as follow

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

This is working perfect but this doesn't make sense since it does not follow DRY principle

Here i've written Blog.object.filter code twice for search. so i want to minimize that and that problem in one line if possible. so could you guys guide over me

CodePudding user response:

You can reduce this using dictionary

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

CodePudding user response:

This is very simple, but a single line would not be readable. .filter doesn't send a query, so the operations can be added one by one. Simple ifs and a few lines make it the most readable form you can achieve here:

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

The oneliner, would be this (since empty string "" parameter in icontains returns all objects):

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

Note: I have changed the names, because camelCase in Python is reserved for class names, variables should use snake_case. That's the convention anyway.

  • Related