Corp/backend/commerce/search.py
2026-08-18 09:28:58 +03:00

48 lines
1.3 KiB
Python

from django.db.backends.signals import connection_created
from django.db.models import CharField, Transform
from django.dispatch import receiver
from rest_framework.filters import SearchFilter
SQLITE_CASEFOLD_FUNCTION = "EUSRR_CASEFOLD"
def _casefold(value):
return None if value is None else str(value).casefold()
@receiver(connection_created, dispatch_uid="commerce.sqlite_unicode_casefold")
def register_sqlite_casefold(sender, connection, **kwargs):
if connection.vendor != "sqlite":
return
connection.connection.create_function(
SQLITE_CASEFOLD_FUNCTION,
1,
_casefold,
deterministic=True,
)
class UnicodeCasefold(Transform):
lookup_name = "unicode_casefold"
function = "LOWER"
output_field = CharField()
def as_sqlite(self, compiler, connection, **extra_context):
return super().as_sql(
compiler,
connection,
function=SQLITE_CASEFOLD_FUNCTION,
**extra_context,
)
CharField.register_lookup(UnicodeCasefold)
class UnicodeCasefoldSearchFilter(SearchFilter):
"""DRF substring search with Unicode-aware case normalization."""
def get_search_terms(self, request):
return [term.casefold() for term in super().get_search_terms(request)]