Icontains And Getlist Django Python
Solution 1:
You can not perform an __icontains with a list, but you can for example design a function that, for a list constructs the logical or of these values. For example:
from django.db.models import Q
from functools import reduce
from operator import or_
defor_fold(list_of_qs):
    if list_of_qs:
        return reduce(or_, list_of_qs)
    else:
        return Q()
defunroll_lists_or(qs, **kwargs):
    return qs.filter([
        or_fold(Q(**{k: vi}) for vi in v)
        for k, v in kwargs.items()
    ])You can then call the unroll_lists_or with a queryset, and each item should be an iterable (for example a list). It will then perform or-logic between the items of the list, and and-logic between different keys. In case an iterable is empty, it is ignored.
So we can then write the check as:
unroll_lists_or(queryset, news_title__icontains=title, news_source=source)In case title contains two items (so title == [title1, title2]), and source contains three items (so source = [source1, source2, source3]), then this will result in:
qs.filter(
    Q(news_title__icontains=title1) | Q(news_title__icontains=title2),
    Q(news_source=source1) | Q(news_source=source2) | Q(news_source=source3)
)
You can however combine it with an .filter(..) for the __in check. For example:
queryset = News.objects.all()
ifsource:
    queryset = queryset.filter(news_source__in=source)
queryset = unroll_lists_or(queryset, news_title__icontains=title)
Solution 2:
I was able to solve this by creating 2 separate functions within the get_querset() function, which is called when a GET request is made.
 def get_queryset(self):
        queryset = News.objects.all()
        source_list = self.request.query_params.getlist('source')
        keyword_list = self.request.query_params.getlist('title')
        if source_list or keyword_list:
            def create_q_source(*args):
                list = [*args]
                source = Q()
                for value in list:
                    source.add(Q(news_source=value), Q.OR)
                return source
            def create_q_keyword(*args):
                list = [*args]
                keyword = Q()
                for value in list:
                    keyword.add(Q(news_title__icontains=value), Q.OR)
                return keyword
            queryset = queryset.filter(create_q_source(*source_list),create_q_keyword(*keyword_list))
        return queryset
Edit: When you go to the api link and pass in the parameters, filtering will occur based on what is passed in:
http://127.0.0.1:8000/api/notes/?keyword=trump&keyword=beyond&keyword=money&source=1SQL Equivalent:
select*from news where news_source =1AND news_title like'%beyond%'OR news_title like'%money%'
Post a Comment for "Icontains And Getlist Django Python"