django icontains with __in lookup

前端 未结 3 1890
庸人自扰
庸人自扰 2020-12-05 01:14

So I want to find any kind of matching given some fields, so for example, this is what I would like to do:

possible_merchants = [\"amazon\", \"web\", \"servi         


        
相关标签:
3条回答
  • 2020-12-05 01:26

    You can create querysets with the Q constructor and combine them with the | operator to get their union:

    from django.db.models import Q
    
    def companies_matching(merchants):
        """
        Return a queryset for companies whose names contain case-insensitive
        matches for any of the `merchants`.
        """
        q = Q()
        for merchant in merchants:
            q |= Q(name__icontains = merchant)
        return Companies.objects.filter(q)
    

    (And similarly with iexact instead of icontains.)

    0 讨论(0)
  • 2020-12-05 01:33

    I find it a cleaner approach using reduce and or_ operator:

    from django.db.models import Q
    from functools import reduce
    from operator import or_
    
    def get_companies_from_merchants(merchant_list):
        q_object = reduce(or_, (Q(name__icontains=merchant) for merchant in merchant_list))
        return Companies.objects.filter(q_object)
    

    This would create a list of Q objects querying the name to contain a single element in merchant list. This would happpen for all the elements in merchant_list and all these Q objects would be reduced to a single Q object having mutliple ORs which can be directly applied to the filter query.

    0 讨论(0)
  • 2020-12-05 01:45

    This is the approach that I adopted:

    class MyManager(models.Manager):
        def exclusive_in(self, lookup, value_list):
            return self.filter(reduce(or_, (Q(**{lookup:_}) for _ in value_list)))
    

    Here is now to use it:

    Companies.objects.exclusive_in('name__icontains', possible_merchants])
    

    It was inspired by other answers in this thread, as well as Django filter queryset __in for *every* item in list.

    0 讨论(0)
提交回复
热议问题