sql «LIKE» équivalent dans la requête django

108

Quel est l'équivalent de cette instruction SQL dans django?

SELECT * FROM table_name WHERE string LIKE pattern;

Comment implémenter cela dans django? j'ai essayé

result = table.objects.filter( pattern in string )

Mais ça n'a pas marché. Comment mettre en œuvre cela?

Aswin Murugesh
la source

Réponses:

200

Utilisez __containsou __icontains(insensible à la casse):

result = table.objects.filter(string__contains='pattern')

L'équivalent SQL est

SELECT ... WHERE string LIKE '%pattern%';
falsetru
la source
22
Et pour la recherche insensible à la casse, utilisez __icontains ->result = table.objects.filter(string__icontains='pattern')
Hitesh Garg
13
Cette réponse ne couvre qu'un sous-ensemble des modèles possibles. Il ne gérerait pas un modèle comme %a%b%.
kasperd
@kasperd, essayez:result = table.objects.filter(string__contains='a').filter(string__contains='b')
LS
1
@LS Cela correspondrait à bace LIKE %a%b%qui ne le serait pas.
kasperd
2
Cette réponse est incomplète pour les raisons exposées ci-dessus. Il devrait également inclure les informations contenues dans la réponse de @ Dmitry.
medley56
34

contient et icontains mentionnés par falsetru font des requêtes comme SELECT ... WHERE headline LIKE '%pattern%

Avec eux, vous pourriez avoir besoin de ceux-ci avec un comportement similaire: commence par , istarts avec , se termine par , iends avec

fabrication

SELECT ... WHERE headline LIKE 'pattern%

ou

SELECT ... WHERE headline LIKE '%pattern

Dmitriy Kuznetsov
la source
9
result = table.objects.filter(string__icontains='pattern')

Recherche insensible à la casse pour une chaîne dans un champ.

Venkat Kotra
la source
2
Bien, mais la même réponse avait déjà été donnée près de trois ans plus tôt.
LS
3

Afin de conserver l'ordre des mots comme dans l'instruction sql LIKE '% pattern%', j'utilise iregex, par exemple:

qs = table.objects.filter(string__iregex=pattern.replace(' ', '.*'))

Les méthodes de chaîne sont immuables, donc votre variable de motif ne changera pas et avec. * vous rechercherez 0 ou plusieurs occurrences de n'importe quel caractère sauf les lignes de rupture.

En utilisant ce qui suit pour parcourir les mots de modèle:

qs = table.objects
for word in pattern.split(' '):
    qs = qs.filter(string__icontains=word)

l'ordre des mots dans votre modèle ne sera pas préservé, pour certaines personnes qui pourraient fonctionner mais dans le cas où j'essaierai d'imiter l'instruction sql like, j'utiliserai la première option.

Rodrigo Ávila
la source
2

Cela peut être fait avec les recherches personnalisées de Django . J'ai fait la recherche dans une application de recherche de type Django . Après l'avoir installé, la __likerecherche avec les caractères génériques %et _sera activée.

Tout le code nécessaire dans l'application est:

from django.db.models import Lookup
from django.db.models.fields import Field


@Field.register_lookup
class Like(Lookup):
    lookup_name = 'like'

    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 LIKE %s' % (lhs, rhs), params
Petr Dlouhý
la source