dj32: adapts lookups/transforms (#74843)
gitea/zoo/pipeline/head There was a failure building this commit Details

* remove django <2.x compatibility code
* use Lower transform/function from Django
* register Lower on CharField
* register text lookup transforms on non contrib JSONField
* declare text transform as outputting CharField type
* fix declaration of timestamp lookup output type
This commit is contained in:
Benjamin Dauvergne 2023-02-24 19:53:15 +01:00
parent 470fea47c3
commit 0440e461be
4 changed files with 18 additions and 68 deletions

View File

@ -16,87 +16,40 @@
import django
from django.db.models import Transform, TextField, DateField
from django.db.models import Transform, CharField, DateField
from django.db.models.functions import Lower
from django.contrib.postgres.fields import jsonb
try:
from django.contrib.postgres.fields.jsonb import KeyTransform, KeyTransformTextLookupMixin
from django.db.models.fields.json import KeyTransform, KeyTransformTextLookupMixin
except ImportError:
# backport from Django 2.x
class KeyTransform(Transform):
operator = '->'
nested_operator = '#>'
def __init__(self, key_name, *args, **kwargs):
super(KeyTransform, self).__init__(*args, **kwargs)
self.key_name = key_name
def as_sql(self, compiler, connection):
key_transforms = [self.key_name]
previous = self.lhs
while isinstance(previous, KeyTransform):
key_transforms.insert(0, previous.key_name)
previous = previous.lhs
lhs, params = compiler.compile(previous)
if len(key_transforms) > 1:
return "(%s %s %%s)" % (lhs, self.nested_operator), [key_transforms] + params
try:
int(self.key_name)
except ValueError:
lookup = "'%s'" % self.key_name
else:
lookup = "%s" % self.key_name
return "(%s %s %s)" % (lhs, self.operator, lookup), params
jsonb.KeyTransform = KeyTransform
class KeyTextTransform(KeyTransform):
operator = '->>'
nested_operator = '#>>'
_output_field = TextField()
class KeyTransformTextLookupMixin(object):
"""
Mixin for combining with a lookup expecting a text lhs from a JSONField
key lookup. Make use of the ->> operator instead of casting key values to
text and performing the lookup on the resulting representation.
"""
def __init__(self, key_transform, *args, **kwargs):
assert isinstance(key_transform, KeyTransform)
key_text_transform = KeyTextTransform(
key_transform.key_name, *key_transform.source_expressions, **key_transform.extra
)
super(KeyTransformTextLookupMixin, self).__init__(key_text_transform, *args, **kwargs)
class Lower(Transform):
lookup_name = 'lower'
function = 'LOWER'
TextField.register_lookup(Lower)
from django.contrib.postgres.fields.jsonb import KeyTransform, KeyTransformTextLookupMixin
class Unaccent(Transform):
lookup_name = 'unaccent'
function = 'immutable_unaccent'
output_field = CharField()
TextField.register_lookup(Unaccent)
CharField.register_lookup(Unaccent)
CharField.register_lookup(Lower)
class Normalize(Transform):
lookup_name = 'normalize'
function = 'immutable_normalize'
output_field = CharField()
TextField.register_lookup(Normalize)
CharField.register_lookup(Normalize)
class Date(Transform):
lookup_name = 'timestamp'
function = 'immutable_date'
_output_field = DateField()
output_field = DateField()
TextField.register_lookup(Date)
CharField.register_lookup(Date)
class JSONUnaccent(KeyTransformTextLookupMixin, Unaccent):

View File

@ -24,6 +24,7 @@ import datetime
from django.db import models, connection
from django.db.models import F, Value
from django.db.models.functions import Lower
from django.db.models.query import QuerySet, Q
from django.core.exceptions import ValidationError
from django.urls import reverse
@ -33,7 +34,7 @@ from django.contrib.postgres.fields import JSONField
from django.contrib.postgres.search import TrigramDistance
from .search import Unaccent, Lower, JSONTextRef
from .search import Unaccent, JSONTextRef
from zoo.zoo_meta.validators import schema_validator
@ -74,7 +75,7 @@ class EntityQuerySet(QuerySet):
for key, value in kwargs.items():
filters.append(Q(**{
'content__' + key + '__unaccent__lower__trigram_similar':
Lower(Unaccent(Value(value))),
Unaccent(Lower(Value(value))),
}))
qs = qs.filter(functools.reduce(__or__, filters))
expressions = []

View File

@ -14,7 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.db.models import Func, Value
from django.db.models import Func, Value, CharField
class Unaccent(Func):
@ -27,11 +27,6 @@ class Normalize(Func):
arity = 1
class Lower(Func):
function = 'LOWER'
arity = 1
class JSONRef(Func):
function = ''
arg_joiner = '->'
@ -46,6 +41,7 @@ class JSONTextRef(Func):
function = ''
arg_joiner = '->>'
arity = 2
output_field = CharField()
def __init__(self, *expressions, **extra):
jsonb = expressions[0]

View File

@ -38,7 +38,7 @@ import psycopg2
from django.conf import settings
from django.contrib.postgres.search import TrigramDistance
from django.db import connection
from django.db.models import Q, F, Value, ExpressionWrapper, CharField, When, Case
from django.db.models import Q, F, Value, ExpressionWrapper, CharField, When, Case, CharField
from django.db.models.functions import Least, Greatest, Coalesce, Concat
from django.db import transaction
from django.contrib.auth.hashers import make_password
@ -541,7 +541,7 @@ class PersonSearch(object):
Coalesce(
JSONTextRef(F('content'), 'nom_d_usage'),
JSONTextRef(F('content'), 'nom_de_naissance'),
Value(' ')
Value(' '),
),
Value(' '),
JSONTextRef(F('content'), 'prenoms'))