diff --git a/cookbook/apps.py b/cookbook/apps.py index a506e060..d133d292 100644 --- a/cookbook/apps.py +++ b/cookbook/apps.py @@ -1,8 +1,11 @@ from django.apps import AppConfig +from django.conf import settings class CookbookConfig(AppConfig): name = 'cookbook' def ready(self): - import cookbook.signals # noqa + # post_save signal is only necessary if using full-text search on postgres + if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']: + import cookbook.signals # noqa diff --git a/cookbook/managers.py b/cookbook/managers.py index beb91dd1..5650d073 100644 --- a/cookbook/managers.py +++ b/cookbook/managers.py @@ -17,8 +17,8 @@ class RecipeSearchManager(models.Manager): ) search_vectors = ( SearchVector('search_vector') - + SearchVector(StringAgg('steps__ingredients__food__name', delimiter=' '), weight='A', config='english') - + SearchVector(StringAgg('keywords__name', delimiter=' '), weight='A', config='english')) + + SearchVector(StringAgg('steps__ingredients__food__name', delimiter=' '), weight='B', config='english') + + SearchVector(StringAgg('keywords__name', delimiter=' '), weight='B', config='english')) search_rank = SearchRank(search_vectors, search_query) # trigram_similarity = TrigramSimilarity( # 'headline', search_text diff --git a/cookbook/migrations/0119_auto_20210407_1828.py b/cookbook/migrations/0119_build_full_text_index.py similarity index 86% rename from cookbook/migrations/0119_auto_20210407_1828.py rename to cookbook/migrations/0119_build_full_text_index.py index ef8be186..9847ccf3 100644 --- a/cookbook/migrations/0119_auto_20210407_1828.py +++ b/cookbook/migrations/0119_build_full_text_index.py @@ -1,5 +1,5 @@ # Generated by Django 3.1.7 on 2021-04-07 20:00 - +from django.conf import settings from django.contrib.postgres.indexes import GinIndex from django.contrib.postgres.search import SearchVectorField, SearchVector from django.db import migrations @@ -8,6 +8,8 @@ from cookbook.models import Recipe def set_default_search_vector(apps, schema_editor): + if settings.DATABASES['default']['ENGINE'] not in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']: + return with scopes_disabled(): search_vector = ( SearchVector('name', weight='A') @@ -16,11 +18,9 @@ def set_default_search_vector(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('cookbook', '0118_auto_20210406_1805'), ] - operations = [ migrations.AddField( model_name='recipe', diff --git a/cookbook/models.py b/cookbook/models.py index c52e0023..fd17f3b9 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -3,6 +3,7 @@ import uuid from datetime import date, timedelta from annoying.fields import AutoOneToOneField +from django.conf import settings from django.contrib import auth from django.contrib.auth.models import Group, User from django.contrib.postgres.indexes import GinIndex @@ -385,10 +386,6 @@ class NutritionInformation(models.Model, PermissionModelMixin): return 'Nutrition' -# TODO adjust model based on DB capabilities -# options to have multiple recipe models based on DB capability (to drive search) -# required_db_features, required-db-vendor -# https://docs.djangoproject.com/en/3.1/ref/models/options/#required-db-vendor class Recipe(models.Model, PermissionModelMixin): name = models.CharField(max_length=128) description = models.CharField(max_length=512, blank=True, null=True) @@ -413,10 +410,15 @@ class Recipe(models.Model, PermissionModelMixin): created_by = models.ForeignKey(User, on_delete=models.PROTECT) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) - search_vector = SearchVectorField(null=True) + search_vector = SearchVectorField(null=True) space = models.ForeignKey(Space, on_delete=models.CASCADE) - objects = ScopedManager(_manager_class=RecipeSearchManager, space='space') + + # load custom manager for full text search if postgress is available + if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']: + objects = ScopedManager(_manager_class=RecipeSearchManager, space='space') + else: + objects = ScopedManager(space='space') def __str__(self): return self.name diff --git a/cookbook/signals.py b/cookbook/signals.py index 5c4cb69f..b282d9ae 100644 --- a/cookbook/signals.py +++ b/cookbook/signals.py @@ -10,12 +10,13 @@ def update_recipe_search_vector(sender, instance=None, created=False, **kwargs): if not instance: return + # needed to ensure search vector update doesn't trigger recursion if hasattr(instance, '_dirty'): return instance.search_vector = ( SearchVector('name', weight='A', config='english') - + SearchVector('description', weight='B', config='english') + + SearchVector('description', weight='C', config='english') ) try: