Compare commits

...

1 Commits

Author SHA1 Message Date
Raphael Michel
173cf751da Add search index model 2019-02-14 18:11:25 +01:00
5 changed files with 130 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
from django.core.management.base import BaseCommand
from django.core.paginator import Paginator
from pretix.base.models import Order, OrderSearchIndex
class Command(BaseCommand):
help = "Rebuild search index"
def add_arguments(self, parser):
parser.add_argument(
'--clean', action='store_true', dest='clean',
help="Clear search index before run.",
)
def iter_pages(self, qs):
paginator = Paginator(qs, 500)
for index in range(paginator.num_pages):
yield paginator.get_page(index + 1)
def handle(self, *args, **options):
if options.get('clean'):
OrderSearchIndex.objects.all().delete()
qs = Order.objects.select_related('event', 'event__organizer', 'invoice_address').prefetch_related('all_positions', 'payments')
for page in self.iter_pages(qs):
if options.get('clean'):
OrderSearchIndex.objects.bulk_create([o.index() for o in page])
else:
for o in page:
o.index()

View File

@@ -0,0 +1,49 @@
# Generated by Django 2.1 on 2019-02-14 10:41
import django.db.models.deletion
from django.db import migrations, models
def create_extension(apps, schema_editor):
if 'postgresql' in schema_editor.connection.settings_dict['ENGINE']:
schema_editor.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm;")
def create_trigram_index(apps, schema_editor):
if 'postgresql' in schema_editor.connection.settings_dict['ENGINE']:
schema_editor.execute("CREATE INDEX pretixbase_ordersearchindex_s ON pretixbase_ordersearchindex USING gin (search_body gin_trgm_ops);")
schema_editor.execute("CREATE INDEX pretixbase_ordersearchindex_spp ON pretixbase_ordersearchindex USING gin (payment_providers gin_trgm_ops);")
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0109_auto_20190208_1432'),
]
operations = [
migrations.RunPython(create_extension),
migrations.CreateModel(
name='OrderSearchIndex',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('search_body', models.TextField()),
('payment_providers', models.TextField()),
],
),
migrations.AddField(
model_name='ordersearchindex',
name='event',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pretixbase.Event'),
),
migrations.AddField(
model_name='ordersearchindex',
name='order',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pretixbase.Order', unique=True),
),
migrations.AddField(
model_name='ordersearchindex',
name='organizer',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pretixbase.Organizer'),
),
migrations.RunPython(create_trigram_index)
]

View File

@@ -7,6 +7,7 @@ from .event import (
Event, Event_SettingsStore, EventLock, EventMetaProperty, EventMetaValue,
RequiredAction, SubEvent, SubEventMetaValue, generate_invite_token,
)
from .index import OrderSearchIndex
from .invoices import Invoice, InvoiceLine, invoice_filename
from .items import (
Item, ItemAddOn, ItemCategory, ItemVariation, Question, QuestionOption,

View File

@@ -0,0 +1,11 @@
from django.db import models
DELIMITER = "\x1F"
class OrderSearchIndex(models.Model):
order = models.ForeignKey('Order', unique=True, null=False, on_delete=models.CASCADE)
event = models.ForeignKey('Event', null=False, on_delete=models.CASCADE)
organizer = models.ForeignKey('Organizer', null=False, on_delete=models.CASCADE)
search_body = models.TextField()
payment_providers = models.TextField()

View File

@@ -693,6 +693,45 @@ class Order(LockModel, LoggedModel):
continue
yield op
def index(self, save=True):
from .index import OrderSearchIndex
indexed_strings = [
self.code,
self.full_code,
self.email,
self.comment,
]
try:
indexed_strings.append(self.invoice_address.name_cached)
indexed_strings.append(self.invoice_address.company)
except InvoiceAddress.DoesNotExist:
pass
for p in self.all_positions.all():
indexed_strings.append(p.attendee_name_cached)
indexed_strings.append(p.attendee_email)
indexed_strings.append(p.secret)
pprovs = set()
for p in self.payments.all():
pprovs.add(p.provider)
if save:
return OrderSearchIndex.objects.update_or_create(
order=self,
defaults={
'event': self.event,
'organizer': self.event.organizer,
'search_body': '\x1E'.join([str(v) for v in indexed_strings if v]),
'payment_providers': '\x1E' + '\x1E'.join([str(v) for v in pprovs if v]) + '\x1E',
}
)[0]
else:
return OrderSearchIndex(
order=self,
event=self.event,
organizer=self.event.organizer,
search_body='\x1E'.join([str(v) for v in indexed_strings if v]),
payment_providers='\x1E' + '\x1E'.join([str(v) for v in pprovs if v]) + '\x1E',
)
def answerfile_name(instance, filename: str) -> str:
secret = get_random_string(length=32, allowed_chars=string.ascii_letters + string.digits)