2013-03-17 22 views
7

In this Frage Problem für Reverse LIKE Operation in SQL, zum Beispiel gelöst wurde, wenn Feldnamen "Peter Johnson" ist, dass wir es durch eine solche Abfrage finden konnte:Django umkehren zu enthält/icontains

select name from user where "Mr. Peter Johnson" like CONCAT('%', name, '%') 

Gibt es jede Möglichkeit, so etwas in Django Q Objekt zu tun (Ich baue eine große Abfrage, so mit rohen SQL-Abfrage wird nicht vernünftig sein)?

Antwort

2

Leider hat Djangos ORM nichts eingebautes für umgekehrte LIKEs. Aber eine Klausel .extra() kann es ein bisschen einfacher als eine rohe Abfrage machen.

habe ich so etwas wie diese:

qs.extra(
    where=['''%s LIKE %s.%s'''], 
    params=(
     "string to match", 
     FooModel._meta.db_table, 
     "bar_field", 
    ), 
) 

Die Probleme mit dem Code oben ist, dass

1) nicht mit SQLite-Backend in dieser Form ("Syntaxfehler in der Nähe von" nicht funktioniert, es funktioniert mit Tabellen-/Spaltennamen, die in Abfragen fest codiert sind ... was nicht immer sicher und immer hässlich ist);

und 2) es erfordert FooModel.bar_field Daten haben %in like style% so kann man nicht beliebige Zeichenkette übereinstimmen (dies kann mit einer Abfrage wie %s LIKE CONCAT("%", %s.%s, "%") festgelegt werden, aber es wird es DBMS-spezifisches machen, was nicht gut ist).

Reversed LIKE selbst sollte wahrscheinlich mit jedem größeren DBMS funktionieren, aber ich habe es nur auf SQLite und Postgres getestet.

Vielleicht soll jemand meine Lösung verallgemeinern und einen wiederverwendbaren, DBMS-unabhängigen App mit speziellem Unterklasse queryset/Manager/Q-Objekt für diese spezifische Aufgabe erstellen ...

-1
output = MyModel.objects.filter(Q(name__contains="Mr. Peter Johnson")) 
+0

Es wird eine normale 'LIKE' Abfrage erzeugt, keine umgekehrte. –

1

Wenn Sie auf der neueste Version von Django sind (1.10 oder höher) und mit Postgres kann das ORM damit umgehen. Check out the docs.

A trigram_similar Nachschlag erhalten Sie, was Sie suchen:

qs = MyModel.objects.filter(name__trigram_similar='Mr. Peter Johnson') 

Vergessen Sie nicht, diese Lookup zu ermöglichen, indem die pg_tgrm Erweiterung ermöglicht. Sie können das mit einer django migration tun.

Und Sie müssen 'django.contrib.postgres' zu Ihrer INSTALLED_APPS Einstellung hinzufügen.