Расширение функциональности фильтра для использования только в том случае, если переменная имеет значение

Я использую фреймворк 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 не посылает запрос, поэтому операции можно добавлять по одной. Простые "если" и несколько строк делают эту форму наиболее читабельной, которую можно получить здесь:

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 возвращает все объекты):

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

Примечание: я изменил имена, потому что camelCase в Python зарезервирован для имен классов, переменные должны использовать snake_case. Такова конвенция в любом случае.

Вернуться на верх