U
U
Untiwe2021-02-14 19:22:03
Django
Untiwe, 2021-02-14 19:22:03

How to make a dynamic number of Q requests?

There is a post search on my site. The user enters a keyword and using the checkbox can choose which field to search for, "author", "post name", "post text"
With all checkboxes enabled, it will look like this

filters = Q(author=keyword) | Q(name=keyword) | Q(text=keyword)
Posts.objects.filter(filters)

With all the checkboxes turned off, it will be so, but this is generally an error (I would like it to just give out all the posts)
filters#переменная не определена, ошибка
Posts.objects.filter(filters)


You can implement this by piling up if else but I think there is a better way

Answer the question

In order to leave comments, you need to log in

3 answer(s)
G
gimntut, 2021-02-15
@Untiwe

Untiwe I modified your code.
All the trick in 2 stars **

def get_queryset(self):
        if not self.request.GET:
            return Posts.objects.all()#если нет параметров, просто возвращаем все посты
        keyword = self.request.GET.get('key')#получаем ключевое слово
        filters = Q()#создаем первый объект Q, что бы складывать с ним другие
        for key in ['author', 'name', 'text']:
                value = self.request.GET.get(key)
                if value:
                        filters |= Q(**{f'{key}__icontains': keyword})
        return Posts.objects.filter(filters)

D
Dr. Bacon, 2021-02-14
@bacon

just with ifs, without else, you can also for on the checkbox list

U
Untiwe, 2021-02-14
@Untiwe

Reply Bacon didn't quite get it, but he did it like this. If anyone needs it, I have a class definition from ListView and a definition of the get_queryset method. This example does not work on its own, but shows the idea

def get_queryset(self):
        if not self.request.GET:
            return Posts.objects.all()#если нет параметров, просто возвращаем все посты

        keyword = self.request.GET.get('key')#получаем ключевое слово
        author= self.request.GET.get('author')#если параметра нет, get() вернет None что равняется False
        name = self.request.GET.get('name')#если параметра нет, get() вернет None что равняется False
        text = self.request.GET.get('text')#если параметра нет, get() вернет None что равняется False
        filters = Q()#создаем первый объект Q, что бы складывать с ним другие
        if author:
            filters |= Q(name__icontains=keyword )
        if name:
            filters |= Q(name__icontains=keyword )
        if text:
            filters |= Q(name__icontains=keyword )
        
        return Posts.objects.filter(filters)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question