web-dev-qa-db-fra.com

Django in / not in query

J'essaie de comprendre comment écrire une requête de style "ne pas entrer" dans Django. Par exemple, la structure de requête à laquelle je pense ressemblerait à ceci.

select table1.* 
from table1
where table1.id not in 
(
  select table2.key_to_table1
  from table2 
  where table2.id = some_parm 
)

À quoi ressemblerait la syntaxe Django en supposant des modèles appelés table1 et table2?

90
Turbo
table1.objects.exclude(id__in=
    table2.objects.filter(your_condition).values_list('id', flat=True))

La fonction exclude fonctionne comme l'opérateur Not que vous demandiez. L'attribut flat = True dit à table2 requête pour retourner le value_list comme une liste à un niveau. Donc ... à la fin, vous obtenez une liste de IDs de la table2, que vous allez utiliser pour définir la condition dans table1, qui sera refusé par la fonction exclure.

148
Harph

avec ces modèles:

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

class table2(models.Model):
    key_to_table1 = models.ForeignKey(table1)

vous devriez obtenir ce que vous voulez en utilisant:

table1.objects.exclude(table2=some_param)
10
Sergio Morstabilini
table1.objects.extra(where=["table1.id NOT IN (SELECT table2.key_to_table1 FROM table2 WHERE table2.id = some_parm)"])
5
ibz

Vous pouvez écrire une recherche personnalisée pour les Django requêtes:

À partir de la documentation : "Commençons par une simple recherche personnalisée. Nous écrirons une recherche personnalisée ne qui fonctionne en face de exact . Author.objects. filter (name__ne = 'Jack') se traduira en 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
1
Blairg23