Como faço para fazer um não igual na filtragem de Queryset de Django?
-
22-08-2019 - |
Pergunta
Em Django Model QuerySets, vejo que existe um __gt
e __lt
para valores comparativos, mas existe um __ne
/!=
/<>
(não é igual?)
Eu quero filtrar usando um não é igual:
Exemplo:
Model:
bool a;
int x;
Eu quero
results = Model.objects.exclude(a=true, x!=5)
o !=
não é a sintaxe correta. eu tentei __ne
, <>
.
Acabei usando:
results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)
Solução
Pode ser Q objetos Pode ser útil para esse problema. Eu nunca os usei, mas parece que eles podem ser negados e combinados como expressões normais do Python.
ATUALIZAÇÃO: Eu apenas experimentei, parece funcionar muito bem:
>>> from myapp.models import Entry
>>> from django.db.models import Q
>>> Entry.objects.filter(~Q(id = 3))
[<Entry: Entry object>, <Entry: Entry object>, <Entry: Entry object>, ...]
Outras dicas
Sua consulta parece ter um duplo negativo, você deseja excluir todas as linhas onde X não é 5; portanto, em outras palavras, você deseja incluir todas as linhas onde X é 5. Acredito que isso fará o truque.
results = Model.objects.filter(x=5).exclude(a=true)
Para responder à sua pergunta específica, não há "não igual a", mas provavelmente porque o Django possui métodos "filtro" e "excluir" disponíveis, para que você sempre possa alternar a rodada lógica para obter o resultado desejado.
a field=value
Sintaxe em consultas é uma abreviação para field__exact=value
. Isto é, dizer isso Django coloca operadores de consulta em campos de consulta nos identificadores. Django suporta os seguintes operadores:
exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
year
month
day
week_day
isnull
search
regex
iregex
Tenho certeza combinando -os com os objetos Q como Dave Vogt sugere e usando filter()
ou exclude()
Como Jason Baker sugere Você obterá exatamente o que precisa para qualquer consulta possível.
É fácil criar uma pesquisa personalizada com o Django 1.7. Há uma __ne
Exemplo de pesquisa em Documentação oficial do Django.
Você precisa criar a pesquisa em si primeiro:
from django.db.models import Lookup
class NotEqual(Lookup):
lookup_name = 'ne'
def as_sql(self, qn, connection):
lhs, lhs_params = self.process_lhs(qn, connection)
rhs, rhs_params = self.process_rhs(qn, connection)
params = lhs_params + rhs_params
return '%s <> %s' % (lhs, rhs), params
Então você precisa registrá -lo:
from django.db.models.fields import Field
Field.register_lookup(NotEqual)
E agora você pode usar o __ne
Pesquisa em suas consultas como esta:
results = Model.objects.exclude(a=True, x__ne=5)
Dentro Django 1.9/1.10 Existem três opções.
-
results = Model.objects.exclude(a=true).filter(x=5)
Usar
Q()
objetos e a~
operadorfrom django.db.models import Q object_list = QuerySet.filter(~Q(a=True), x=5)
Registro a função de pesquisa personalizada
from django.db.models import Lookup from django.db.models.fields import Field @Field.register_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
o
register_lookup
Decorador foi adicionado em Django 1.8 e permite uma pesquisa personalizada como de costume:results = Model.objects.exclude(a=True, x__ne=5)
Enquanto com os modelos, você pode filtrar com =
, __gt
, __gte
, __lt
, __lte
, você não pode usar ne
, !=
ou <>
. No entanto, você pode obter melhor filtragem ao usar o objeto Q.
Você pode evitar acorrentar QuerySet.filter()
e QuerySet.exlude()
, e use isto:
from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')
Decisão de design pendente. Enquanto isso, use exclude()
O rastreador de edição do django tem o notável Entrada #5763, intitulado "Queryset não tem um operador de filtro" não igual ". É notável porque (em abril de 2016) foi "aberto há 9 anos" (na Idade da Pedra de Django), "fechado há 4 anos" e "mudou pela última vez 5 meses atrás".
Leia a discussão, é interessante. Basicamente, algumas pessoas discutem __ne
deve ser adicionado enquanto outros dizem exclude()
é mais claro e, portanto, __ne
deve não ser adicionado.
(Eu concordo com o primeiro, porque o último argumento é aproximadamente equivalente a dizer que Python não deveria ter !=
porque tem ==
e not
já...)
Você deveria usar filter
e exclude
assim
results = Model.objects.exclude(a=true).filter(x=5)
Usando excluir e filtrar
results = Model.objects.filter(x=5).exclude(a=true)
O último bit de código excluirá todos os objetos em que x! = 5 e a é verdadeiro. Experimente isso:
results = Model.objects.filter(a=False, x=5)
Lembre -se, o = sinal na linha acima está atribuindo false ao parâmetro A e o número 5 ao parâmetro x. Não está checando a igualdade. Portanto, não há realmente nenhuma maneira de usar o símbolo! = Em uma chamada de consulta.
O que você está procurando são todos objetos que têm a=false
ou x=5
. Em Django, |
serve como OR
Operador entre os consultas:
results = Model.objects.filter(a=false)|Model.objects.filter(x=5)
results = Model.objects.filter(a = True).exclude(x = 5)Genetes este SQL:
select * from tablex where a != 0 and x !=5O SQL depende de como seu campo verdadeiro/falso é representado e do mecanismo de banco de dados. O código Django é tudo o que você precisa.
Valores Django-Modelo (Divulgação: Autor) fornece uma implementação do Não igual pesquisa, como em esta resposta. Ele também fornece suporte sintático para ele:
from model_values import F
Model.objects.exclude(F.x != 5, a=True)
Cuidado com muitas respostas incorretas para esta pergunta!
A lógica de Gerard está correta, embora retorne uma lista em vez de uma consulta (o que pode não importar).
Se você precisar de uma consulta, use Q:
from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))