diff --git a/fedireads/books_manager.py b/fedireads/books_manager.py index 9810dc8d..56fdcdcf 100644 --- a/fedireads/books_manager.py +++ b/fedireads/books_manager.py @@ -29,49 +29,47 @@ def load_more_data(book_id): connector.expand_book_data(book) -def search(query): - ''' try an external datasource for books ''' - self = self_connector() - results = self.search(query) - if len(results) >= 10: - return results - - connector = get_connector() - external_results = connector.search(query) - dedupe_slug = lambda r: '%s %s %s' % (r.title, r.author, r.year) - result_index = [dedupe_slug(r) for r in results] - for result in external_results: - if dedupe_slug(result) in result_index: - continue - results.append(result) +def search(query, first=False): + ''' find books based on arbitary keywords ''' + results = [] + for connector in get_connectors(): + result = connector.search(query) + if first and result: + return result[0] + results.append({ + 'connector': connector, + 'results': result, + }) return results + def update_book(book): ''' re-sync with the original data source ''' connector = get_connector(book) connector.update_book(book) -def self_connector(): - ''' load the connector for the local database ''' - return get_connector(self=True) +def get_connectors(): + ''' load all connectors ''' + connectors_info = models.Connector.objects.order_by('priority').all() + return [load_connector(c) for c in connectors_info] -def get_connector(book=None, self=False): +def get_connector(book=None): ''' pick a book data connector ''' if book and book.connector: connector_info = book.connector - elif self: - connector_info = models.Connector.objects.filter( - connector_file='self_connector' - ).first() else: # only select from external connectors - connector_info = models.Connector.objects.exclude( - connector_file='self_connector' - ).first() + connector_info = models.Connector.objects.filter( + self=False + ).order_by('priority').first() + return load_connector(connector_info) + +def load_connector(connector_info): + ''' instantiate the connector class ''' connector = importlib.import_module( 'fedireads.connectors.%s' % connector_info.connector_file ) diff --git a/fedireads/connectors/abstract_connector.py b/fedireads/connectors/abstract_connector.py index 6eb864a0..3a49d2a9 100644 --- a/fedireads/connectors/abstract_connector.py +++ b/fedireads/connectors/abstract_connector.py @@ -14,11 +14,14 @@ class AbstractConnector(ABC): info = models.Connector.objects.get(identifier=identifier) self.connector = info - self.url = info.base_url + self.base_url = info.base_url + self.books_url = info.books_url self.covers_url = info.covers_url self.search_url = info.search_url self.key_name = info.key_name self.max_query_count = info.max_query_count + self.name = info.name + self.self = info.self def is_available(self): diff --git a/fedireads/migrations/0036_auto_20200503_1952.py b/fedireads/migrations/0036_auto_20200503_1952.py new file mode 100644 index 00000000..9c931d35 --- /dev/null +++ b/fedireads/migrations/0036_auto_20200503_1952.py @@ -0,0 +1,39 @@ +# Generated by Django 3.0.3 on 2020-05-03 19:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fedireads', '0035_auto_20200429_1708'), + ] + + operations = [ + migrations.AddField( + model_name='connector', + name='books_url', + field=models.CharField(default='https://openlibrary.org', max_length=255), + preserve_default=False, + ), + migrations.AddField( + model_name='connector', + name='name', + field=models.CharField(max_length=255, null=True), + ), + migrations.AddField( + model_name='connector', + name='priority', + field=models.IntegerField(default=2), + ), + migrations.AddField( + model_name='connector', + name='self', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='connector', + name='connector_file', + field=models.CharField(choices=[('openlibrary', 'Openlibrary'), ('self_connector', 'Self Connector'), ('fedireads_connector', 'Fedireads Connector')], max_length=255), + ), + ] diff --git a/fedireads/models/book.py b/fedireads/models/book.py index e501fc6b..630ca43f 100644 --- a/fedireads/models/book.py +++ b/fedireads/models/book.py @@ -16,14 +16,17 @@ ConnectorFiles = models.TextChoices('ConnectorFiles', CONNECTORS) class Connector(FedireadsModel): ''' book data source connectors ''' identifier = models.CharField(max_length=255, unique=True) + priority = models.IntegerField(default=2) + name = models.CharField(max_length=255, null=True) + self = models.BooleanField(default=False) connector_file = models.CharField( max_length=255, - default='openlibrary', choices=ConnectorFiles.choices ) api_key = models.CharField(max_length=255, null=True) base_url = models.CharField(max_length=255) + books_url = models.CharField(max_length=255) covers_url = models.CharField(max_length=255) search_url = models.CharField(max_length=255, null=True) diff --git a/fedireads/models/import_job.py b/fedireads/models/import_job.py index 72ff2e73..7c703080 100644 --- a/fedireads/models/import_job.py +++ b/fedireads/models/import_job.py @@ -67,9 +67,9 @@ class ImportItem(models.Model): def get_book_from_isbn(self): ''' search by isbn ''' - search_results = books_manager.search(self.isbn) - if search_results: - return books_manager.get_or_create_book(search_results[0].key) + search_result = books_manager.search(self.isbn, first=True) + if search_result: + return books_manager.get_or_create_book(search_result.key) def get_book_from_title_author(self): ''' search by title and author ''' @@ -77,9 +77,9 @@ class ImportItem(models.Model): self.data['Title'], self.data['Author'] ) - search_results = books_manager.search(search_term) - if search_results: - return books_manager.get_or_create_book(search_results[0].key) + search_result = books_manager.search(search_term, first=True) + if search_result: + return books_manager.get_or_create_book(search_result.key) @property def isbn(self): diff --git a/fedireads/static/format.css b/fedireads/static/format.css index 68f901f2..670da18a 100644 --- a/fedireads/static/format.css +++ b/fedireads/static/format.css @@ -45,6 +45,10 @@ h3 small { font-weight: normal; } +section { + margin-bottom: 1em; +} + /* fixed display top bar */ body { diff --git a/fedireads/templates/book_results.html b/fedireads/templates/book_results.html index bb7fa735..e7a21c6b 100644 --- a/fedireads/templates/book_results.html +++ b/fedireads/templates/book_results.html @@ -1,13 +1,21 @@ {% extends 'layout.html' %} {% block content %} -
-
-

Search results

- {% for result in results %} +
+

Search results

+ {% for result_set in results %} +
+ {% if not result_set.connector.self %} +

+ Results from {{ result_set.connector.name }} +

+ {% endif %} + + {% for result in result_set.results %}
- {{ result.title }} by {{ result.author }} ({{ result.year }}) + {{ result.title }} by {{ result.author }} ({{ result.year }})
{% endfor %} -
+ + {% endfor %}
{% endblock %} diff --git a/init_db.py b/init_db.py index 13f93f01..edd3dea6 100644 --- a/init_db.py +++ b/init_db.py @@ -13,8 +13,10 @@ User.objects.get(id=1).followers.add(User.objects.get(id=2)) Connector.objects.create( identifier='openlibrary.org', + name='OpenLibrary', connector_file='openlibrary', base_url='https://openlibrary.org', + books_url='https://openlibrary.org', covers_url='https://covers.openlibrary.org', search_url='https://openlibrary.org/search?q=', key_name='openlibrary_key', @@ -22,11 +24,15 @@ Connector.objects.create( Connector.objects.create( identifier=DOMAIN, + name='Local', + self=True, connector_file='self_connector', - base_url='https://%s/book' % DOMAIN, + base_url='https://%s' % DOMAIN, + books_url='https://%s/book' % DOMAIN, covers_url='https://%s/images/covers' % DOMAIN, search_url='https://%s/search?q=' % DOMAIN, key_name='openlibrary_key', + priority=1, )