From 21ae6d580b73b6a180a25b8514e5446d61bb888e Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 1 Mar 2022 14:45:49 +0100 Subject: [PATCH] Search by metadata. --- src/documents/migrations/0007_book_dc.py | 18 ++++++++++++++++++ src/documents/models/book.py | 12 +++++++++++- src/documents/templatetags/book_list.py | 22 ++++++++++++++++------ 3 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 src/documents/migrations/0007_book_dc.py diff --git a/src/documents/migrations/0007_book_dc.py b/src/documents/migrations/0007_book_dc.py new file mode 100644 index 00000000..4daf828d --- /dev/null +++ b/src/documents/migrations/0007_book_dc.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.13 on 2022-03-01 14:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('documents', '0006_auto_20210706_0130'), + ] + + operations = [ + migrations.AddField( + model_name='book', + name='dc', + field=models.JSONField(editable=False, null=True), + ), + ] diff --git a/src/documents/models/book.py b/src/documents/models/book.py index d5724a24..e649180d 100644 --- a/src/documents/models/book.py +++ b/src/documents/models/book.py @@ -3,7 +3,7 @@ # from django.apps import apps from django.contrib.sites.models import Site -from django.db import models, transaction +from django.db import connection, models, transaction from django.template.loader import render_to_string from django.urls import reverse from django.utils.translation import ugettext_lazy as _ @@ -41,6 +41,7 @@ class Book(models.Model): _on_track = models.IntegerField(null=True, blank=True, db_index=True, editable=False) dc_cover_image = models.ForeignKey(Image, blank=True, null=True, db_index=True, on_delete=models.SET_NULL, editable=False) + dc = models.JSONField(null=True, editable=False) catalogue_book = models.ForeignKey( 'catalogue.Book', models.DO_NOTHING, @@ -68,6 +69,14 @@ class Book(models.Model): qs = qs.filter(public=True) return qs + @staticmethod + def q_dc(field, field_plural, value, prefix=''): + if connection.features.supports_json_field_contains: + return models.Q(**{f'{prefix}dc__{field_plural}__contains': value}) + else: + return models.Q(**{f'{prefix}dc__{field}': value}) + + # Representing # ============ @@ -367,6 +376,7 @@ class Book(models.Model): else: if info.cover_source == image.get_full_url(): update['dc_cover_image'] = image + update['dc'] = info.to_dict() Book.objects.filter(pk=self.pk).update(**update) def touch(self): diff --git a/src/documents/templatetags/book_list.py b/src/documents/templatetags/book_list.py index bf5fbd09..88120d20 100644 --- a/src/documents/templatetags/book_list.py +++ b/src/documents/templatetags/book_list.py @@ -1,12 +1,12 @@ # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # -from re import split +import re from django.db.models import Q, Count, F, Max from django import template from django.utils.translation import ugettext_lazy as _ from django.contrib.auth.models import User -from documents.models import Chunk, Image, Project +from documents.models import Book, Chunk, Image, Project register = template.Library() @@ -70,10 +70,20 @@ def foreign_filter(qs, value, filter_field, model, model_field='slug', unset='-' def search_filter(qs, value, filter_fields): if not value: return qs - q = Q(**{"%s__icontains" % filter_fields[0]: value}) - for field in filter_fields[1:]: - q |= Q(**{"%s__icontains" % field: value}) - return qs.filter(q) + + for word in value.split(): + m = re.match(r'(.+):(.+)', word) + if m is not None: + field = m.group(1) + value = m.group(2) + q = Book.q_dc(field, field + 's', value, 'book__') + else: + q = Q(**{"%s__icontains" % filter_fields[0]: value}) + for field in filter_fields[1:]: + q |= Q(**{"%s__icontains" % field: value}) + qs = qs.filter(q) + + return qs _states = [ -- 2.20.1