Django in / not in query

前端 未结 6 1777
不知归路
不知归路 2020-12-02 14:56

I\'m trying to figure out how to write a \'not in\' style query in django. For example, the query structure I\'m thinking of would look like this.

select tab         


        
相关标签:
6条回答
  • 2020-12-02 15:26

    You can write a custom lookup for Django queries:

    From the documentation: "Let’s start with a simple custom lookup. We will write a custom lookup ne which works opposite to exact. Author.objects.filter(name__ne='Jack') will translate to the SQL: "author"."name" <> 'Jack'"

    from django.db.models import Lookup
    
    class NotEqual(Lookup):
        lookup_name = 'ne'
    
        def as_sql(self, compiler, connection):
            lhs, lhs_params = self.process_lhs(compiler, connection)
            rhs, rhs_params = self.process_rhs(compiler, connection)
            params = lhs_params + rhs_params
            return '%s <> %s' % (lhs, rhs), params
    
    0 讨论(0)
  • 2020-12-02 15:30
    table1.objects.extra(where=["table1.id NOT IN (SELECT table2.key_to_table1 FROM table2 WHERE table2.id = some_parm)"])
    
    0 讨论(0)
  • 2020-12-02 15:34
    [o1 for o1 in table1.objects.all() if o1.id not in [o2.id for o2 in table2.objects.filter(id=some_parm)]]
    

    Or better

    not_in_ids = [obj.id for obj in table2.objects.filter(id=some_parm)]
    selected_objects = [obj for obj in table1.objects.iterator() if obj.id not in not_in_ids]
    
    0 讨论(0)
  • 2020-12-02 15:40

    with these models:

    class table1(models.Model):
        field1 = models.CharField(max_length=10)      # a dummy field
    
    class table2(models.Model):
        key_to_table1 = models.ForeignKey(table1)
    

    you should get what you want using:

    table1.objects.exclude(table2=some_param)
    
    0 讨论(0)
  • 2020-12-02 15:41

    The accepted answer is ok but I'm going to provide a new approach which is more operable.

    from django.db.models import Q
    
    query = Q(id__in=table2.objects.filter(your_condition).values_list('id'))
    table1.objects.filter(~query)
    

    If you are using the primary key the call to values_list() is not necessary.

    The "~" on Q() object acts like "not" operator.

    I guess this approach makes the code more reusable and allows you to do "any" sort of dynamic stuff just by storing your Q() objects on vars.

    0 讨论(0)
  • 2020-12-02 15:48
    table1.objects.exclude(id__in=
        table2.objects.filter(your_condition).values_list('id', flat=True))
    

    The exclude function works like the Not operator you where asking for. The attribute flat = True tells to table2 query to return the value_list as a one level list. So... at the end you are obtaining a list of IDs from table2, which you are going to user to define the condition in table1, that will be denied by the exclude function.

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