news trigram search
This commit is contained in:
parent
de50d6491f
commit
6a36bb5a13
|
|
@ -1,6 +1,8 @@
|
|||
"""Filters from application News"""
|
||||
from django_filters import rest_framework as filters
|
||||
from django.core.validators import EMPTY_VALUES
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_filters import rest_framework as filters
|
||||
from rest_framework.serializers import ValidationError
|
||||
|
||||
from news import models
|
||||
|
||||
|
|
@ -29,6 +31,7 @@ class NewsListFilterSet(filters.FilterSet):
|
|||
(SORT_BY_START_CHOICE, "start"),
|
||||
)
|
||||
sort_by = filters.ChoiceFilter(method='sort_by_field', choices=SORT_BY_CHOICES)
|
||||
search = filters.CharFilter(method='search_news')
|
||||
|
||||
class Meta:
|
||||
"""Meta class"""
|
||||
|
|
@ -41,8 +44,16 @@ class NewsListFilterSet(filters.FilterSet):
|
|||
'tag_value__in',
|
||||
'state',
|
||||
'sort_by',
|
||||
'search',
|
||||
)
|
||||
|
||||
def search_news(self, queryset, name, value):
|
||||
if value not in EMPTY_VALUES:
|
||||
if len(value) < 3:
|
||||
raise ValidationError({'detail': _('Type at least 3 characters to search please.')})
|
||||
return queryset.trigram_search(value)
|
||||
return queryset
|
||||
|
||||
def in_tags(self, queryset, name, value):
|
||||
tags = value.split('__')
|
||||
return queryset.filter(tags__value__in=tags)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ from django.contrib.contenttypes import fields as generic
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.postgres.fields import HStoreField
|
||||
from django.db import models
|
||||
from django.db.models import Case, When
|
||||
from django.db.models import Case, When, Q, F
|
||||
from django.db.models.functions import Cast
|
||||
from django.contrib.postgres.search import TrigramSimilarity
|
||||
from django.urls.exceptions import NoReverseMatch
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
|
@ -144,6 +146,46 @@ class NewsQuerySet(TranslationQuerysetMixin):
|
|||
def by_locale(self, locale):
|
||||
return self.filter(title__icontains=locale)
|
||||
|
||||
def trigram_search(self, search_value: str):
|
||||
"""Search with mistakes by name or last name."""
|
||||
return self.annotate(
|
||||
description_str=Cast('description', models.TextField()),
|
||||
title_str=Cast('title', models.TextField()),
|
||||
subtitle_str=Cast('subtitle', models.TextField()),
|
||||
search_contains_match=Case(
|
||||
models.When(Q(description_str__icontains=search_value) | Q(title_str__icontains=search_value) | Q(
|
||||
subtitle_str__icontains=search_value), then=100),
|
||||
default=0,
|
||||
output_field=models.FloatField(),
|
||||
),
|
||||
description_similarity=models.Case(
|
||||
models.When(
|
||||
Q(description__isnull=False),
|
||||
then=TrigramSimilarity('description_str', search_value.lower()),
|
||||
),
|
||||
default=0,
|
||||
output_field=models.FloatField()
|
||||
),
|
||||
title_similarity=models.Case(
|
||||
models.When(
|
||||
Q(title__isnull=False),
|
||||
then=TrigramSimilarity('title_str', search_value.lower()),
|
||||
),
|
||||
default=0,
|
||||
output_field=models.FloatField()
|
||||
),
|
||||
subtitle_similarity=models.Case(
|
||||
models.When(
|
||||
Q(subtitle__isnull=False),
|
||||
then=TrigramSimilarity('subtitle_str', search_value.lower()),
|
||||
),
|
||||
default=0,
|
||||
output_field=models.FloatField()
|
||||
),
|
||||
relevance=(F('search_contains_match') + F('description_similarity') + F('title_similarity') + F(
|
||||
'subtitle_similarity'))
|
||||
).filter(relevance__gte=0.3).order_by('-relevance')
|
||||
|
||||
|
||||
class News(GalleryMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixin,
|
||||
FavoritesMixin):
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user