Add Query/QueryDailyHits models into search promotions

pull/10161/head^2
Karl Hobley 2021-06-22 15:56:24 +01:00 zatwierdzone przez LB (Ben Johnston)
rodzic ef438ae3c0
commit 2566f0431d
5 zmienionych plików z 166 dodań i 2 usunięć

Wyświetl plik

@ -0,0 +1,16 @@
from django.core.management.base import BaseCommand
from wagtail.contrib.search_promotions import models
class Command(BaseCommand):
def handle(self, **options):
# Clean daily hits
self.stdout.write("Cleaning daily hits records…")
models.QueryDailyHits.garbage_collect()
self.stdout.write("Done")
# Clean queries
self.stdout.write("Cleaning query records…")
models.Query.garbage_collect()
self.stdout.write("Done")

Wyświetl plik

@ -0,0 +1,58 @@
# Generated by Django 3.1.8 on 2021-06-22 14:19
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("wagtailsearchpromotions", "0002_capitalizeverbose"),
]
operations = [
migrations.CreateModel(
name="Query",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("query_string", models.CharField(max_length=255, unique=True)),
],
),
migrations.CreateModel(
name="QueryDailyHits",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("date", models.DateField()),
("hits", models.IntegerField(default=0)),
(
"query",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="daily_hits",
to="wagtailsearchpromotions.query",
),
),
],
options={
"verbose_name": "Query Daily Hits",
"verbose_name_plural": "Query Daily Hits",
"unique_together": {("query", "date")},
},
),
]

Wyświetl plik

@ -1,12 +1,102 @@
import datetime
from django.conf import settings
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from wagtail.search.models import Query
from wagtail.search.models import Query as WagtailSearchQuery
from wagtail.search.utils import MAX_QUERY_STRING_LENGTH, normalise_query_string
class Query(models.Model):
query_string = models.CharField(max_length=MAX_QUERY_STRING_LENGTH, unique=True)
def save(self, *args, **kwargs):
# Normalise query string
self.query_string = normalise_query_string(self.query_string)
super().save(*args, **kwargs)
def add_hit(self, date=None):
if date is None:
date = timezone.now().date()
daily_hits, created = QueryDailyHits.objects.get_or_create(
query=self, date=date
)
daily_hits.hits = models.F("hits") + 1
daily_hits.save()
def __str__(self):
return self.query_string
@property
def hits(self):
hits = self.daily_hits.aggregate(models.Sum("hits"))["hits__sum"]
return hits if hits else 0
@classmethod
def garbage_collect(cls):
"""
Deletes all Query records that have no daily hits or editors picks
"""
extra_filter_kwargs = (
{
"editors_picks__isnull": True,
}
if hasattr(cls, "editors_picks")
else {}
)
cls.objects.filter(daily_hits__isnull=True, **extra_filter_kwargs).delete()
@classmethod
def get(cls, query_string):
return cls.objects.get_or_create(
query_string=normalise_query_string(query_string)
)[0]
@classmethod
def get_most_popular(cls, date_since=None):
# TODO: Implement date_since
return (
cls.objects.filter(daily_hits__isnull=False)
.annotate(_hits=models.Sum("daily_hits__hits"))
.distinct()
.order_by("-_hits")
)
class QueryDailyHits(models.Model):
query = models.ForeignKey(
Query, db_index=True, related_name="daily_hits", on_delete=models.CASCADE
)
date = models.DateField()
hits = models.IntegerField(default=0)
@classmethod
def garbage_collect(cls, days=None):
"""
Deletes all QueryDailyHits records that are older than a set number of days
"""
days = (
getattr(settings, "WAGTAILSEARCH_HITS_MAX_AGE", 7) if days is None else days
)
min_date = timezone.now().date() - datetime.timedelta(days)
cls.objects.filter(date__lt=min_date).delete()
class Meta:
unique_together = (("query", "date"),)
verbose_name = _("Query Daily Hits")
verbose_name_plural = _("Query Daily Hits")
class SearchPromotion(models.Model):
query = models.ForeignKey(
Query, db_index=True, related_name="editors_picks", on_delete=models.CASCADE
WagtailSearchQuery,
db_index=True,
related_name="editors_picks",
on_delete=models.CASCADE,
)
page = models.ForeignKey(
"wagtailcore.Page", verbose_name=_("page"), on_delete=models.CASCADE