news trigram search
This commit is contained in:
parent
de50d6491f
commit
6a36bb5a13
|
|
@ -1,6 +1,8 @@
|
||||||
"""Filters from application News"""
|
"""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.utils.translation import gettext_lazy as _
|
||||||
|
from django_filters import rest_framework as filters
|
||||||
|
from rest_framework.serializers import ValidationError
|
||||||
|
|
||||||
from news import models
|
from news import models
|
||||||
|
|
||||||
|
|
@ -29,6 +31,7 @@ class NewsListFilterSet(filters.FilterSet):
|
||||||
(SORT_BY_START_CHOICE, "start"),
|
(SORT_BY_START_CHOICE, "start"),
|
||||||
)
|
)
|
||||||
sort_by = filters.ChoiceFilter(method='sort_by_field', choices=SORT_BY_CHOICES)
|
sort_by = filters.ChoiceFilter(method='sort_by_field', choices=SORT_BY_CHOICES)
|
||||||
|
search = filters.CharFilter(method='search_news')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class"""
|
"""Meta class"""
|
||||||
|
|
@ -41,8 +44,16 @@ class NewsListFilterSet(filters.FilterSet):
|
||||||
'tag_value__in',
|
'tag_value__in',
|
||||||
'state',
|
'state',
|
||||||
'sort_by',
|
'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):
|
def in_tags(self, queryset, name, value):
|
||||||
tags = value.split('__')
|
tags = value.split('__')
|
||||||
return queryset.filter(tags__value__in=tags)
|
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.contenttypes.models import ContentType
|
||||||
from django.contrib.postgres.fields import HStoreField
|
from django.contrib.postgres.fields import HStoreField
|
||||||
from django.db import models
|
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.urls.exceptions import NoReverseMatch
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
@ -144,6 +146,46 @@ class NewsQuerySet(TranslationQuerysetMixin):
|
||||||
def by_locale(self, locale):
|
def by_locale(self, locale):
|
||||||
return self.filter(title__icontains=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,
|
class News(GalleryMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixin,
|
||||||
FavoritesMixin):
|
FavoritesMixin):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user