0002-authentic2-add-full-text-search-to-AttributeValue-49.patch
src/authentic2/managers.py | ||
---|---|---|
23 | 23 |
from django.utils.timezone import now |
24 | 24 |
from django.conf import settings |
25 | 25 |
from django.contrib.contenttypes.models import ContentType |
26 |
from django.contrib.postgres.search import SearchVector |
|
26 | 27 | |
27 | 28 |
from django_rbac.utils import get_ou_model |
28 | 29 |
from model_utils import managers |
... | ... | |
86 | 87 |
raise AttributeValue.DoesNotExist |
87 | 88 |
return self.get(content_type=ct, object_id=owner.pk, attribute=at) |
88 | 89 | |
90 |
def update_search_vectors(self): |
|
91 |
self.update(search_vector=SearchVector('content')) |
|
92 | ||
89 | 93 | |
90 | 94 |
class ServiceQuerySet(managers.InheritanceQuerySetMixin, GetBySlugQuerySet): |
91 | 95 |
pass |
src/authentic2/migrations/0031_add_search_vector_to_attributes.py | ||
---|---|---|
1 |
import django.contrib.postgres.indexes |
|
2 |
import django.contrib.postgres.search |
|
3 |
from django.db import migrations |
|
4 | ||
5 | ||
6 |
def create_trigger(apps, schema_editor): |
|
7 |
with schema_editor.connection.cursor() as cursor: |
|
8 |
cursor.execute('SHOW default_text_search_config') |
|
9 |
default_text_search_config, = cursor.fetchone() |
|
10 |
cursor.execute('''CREATE OR REPLACE FUNCTION authentic2_update_atv_search_vector() RETURNS TRIGGER AS $$ |
|
11 |
BEGIN |
|
12 |
IF TG_OP = 'INSERT' OR (TG_OP = 'UPDATE' AND NEW.content <> OLD.content) THEN |
|
13 |
NEW.search_vector = to_tsvector(NEW.content); |
|
14 |
END IF; |
|
15 |
RETURN NEW; |
|
16 |
END; $$ LANGUAGE plpgsql''') |
|
17 |
cursor.execute('''CREATE TRIGGER authentic2_attributevalue_search_vector_trigger |
|
18 |
BEFORE INSERT OR UPDATE OF content |
|
19 |
ON authentic2_attributevalue |
|
20 |
FOR EACH ROW EXECUTE PROCEDURE authentic2_update_atv_search_vector()''') |
|
21 | ||
22 | ||
23 |
def drop_trigger(apps, schema_editor): |
|
24 |
with schema_editor.connection.cursor() as cursor: |
|
25 |
cursor.execute('DROP TRIGGER authentic2_attributevalue_search_vector_trigger') |
|
26 | ||
27 | ||
28 |
class Migration(migrations.Migration): |
|
29 |
dependencies = [ |
|
30 |
('authentic2', '0030_clean_admin_tools_tables'), |
|
31 |
] |
|
32 | ||
33 |
operations = [ |
|
34 |
migrations.AddField( |
|
35 |
model_name='attributevalue', |
|
36 |
name='search_vector', |
|
37 |
field=django.contrib.postgres.search.SearchVectorField(editable=False, null=True), |
|
38 |
), |
|
39 |
migrations.AddIndex( |
|
40 |
model_name='attributevalue', |
|
41 |
index=django.contrib.postgres.indexes.GinIndex(fields=['search_vector'], name='authentic2_atv_tsvector_idx') |
|
42 |
), |
|
43 |
migrations.RunPython(create_trigger, drop_trigger), |
|
44 | ||
45 |
] |
src/authentic2/migrations/0032_initialize_search_vectors.py | ||
---|---|---|
1 |
# Generated by Django 2.2.17 on 2021-01-16 14:22 |
|
2 | ||
3 |
from django.contrib.postgres.search import SearchVector |
|
4 |
from django.db import migrations |
|
5 | ||
6 | ||
7 |
def initialize_search_vector(apps, schema_editor): |
|
8 |
AttributeValue = apps.get_model('authentic2', 'AttributeValue') |
|
9 |
AttributeValue.all_objects.update(search_vector=SearchVector('content')) |
|
10 | ||
11 | ||
12 |
class Migration(migrations.Migration): |
|
13 |
dependencies = [ |
|
14 |
('authentic2', '0031_add_search_vector_to_attributes'), |
|
15 |
] |
|
16 | ||
17 |
operations = [ |
|
18 |
migrations.RunPython(initialize_search_vector, reverse_code=migrations.RunPython.noop), |
|
19 |
] |
src/authentic2/models.py | ||
---|---|---|
29 | 29 |
from django.core.exceptions import ValidationError |
30 | 30 |
from django.contrib.contenttypes.models import ContentType |
31 | 31 |
from django.contrib.postgres.fields import jsonb |
32 |
from django.contrib.postgres.search import SearchVectorField |
|
33 |
from django.contrib.postgres.indexes import GinIndex |
|
32 | 34 | |
33 | 35 |
from model_utils.managers import QueryManager |
34 | 36 | |
... | ... | |
319 | 321 |
multiple = models.BooleanField(default=False, null=True) |
320 | 322 | |
321 | 323 |
content = models.TextField(verbose_name=_('content'), db_index=True) |
324 |
search_vector = SearchVectorField(null=True, editable=False) |
|
322 | 325 |
verified = models.BooleanField(default=False) |
323 | 326 | |
324 | 327 |
all_objects = managers.AttributeValueManager() |
... | ... | |
341 | 344 |
unique_together = ( |
342 | 345 |
('content_type', 'object_id', 'attribute', 'multiple', 'content'), |
343 | 346 |
) |
347 |
indexes = [ |
|
348 |
GinIndex(fields=['search_vector'], name='authentic2_atv_tsvector_idx'), |
|
349 |
] |
|
344 | 350 | |
345 | 351 | |
346 | 352 |
class PasswordReset(models.Model): |
347 |
- |