forked from mirrors/bookwyrm
Separate out local and remote search results
This commit is contained in:
parent
d8934879e9
commit
7fb0a87077
8 changed files with 102 additions and 41 deletions
|
@ -29,49 +29,47 @@ def load_more_data(book_id):
|
||||||
connector.expand_book_data(book)
|
connector.expand_book_data(book)
|
||||||
|
|
||||||
|
|
||||||
def search(query):
|
def search(query, first=False):
|
||||||
''' try an external datasource for books '''
|
''' find books based on arbitary keywords '''
|
||||||
self = self_connector()
|
results = []
|
||||||
results = self.search(query)
|
for connector in get_connectors():
|
||||||
if len(results) >= 10:
|
result = connector.search(query)
|
||||||
return results
|
if first and result:
|
||||||
|
return result[0]
|
||||||
connector = get_connector()
|
results.append({
|
||||||
external_results = connector.search(query)
|
'connector': connector,
|
||||||
dedupe_slug = lambda r: '%s %s %s' % (r.title, r.author, r.year)
|
'results': result,
|
||||||
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)
|
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def update_book(book):
|
def update_book(book):
|
||||||
''' re-sync with the original data source '''
|
''' re-sync with the original data source '''
|
||||||
connector = get_connector(book)
|
connector = get_connector(book)
|
||||||
connector.update_book(book)
|
connector.update_book(book)
|
||||||
|
|
||||||
|
|
||||||
def self_connector():
|
def get_connectors():
|
||||||
''' load the connector for the local database '''
|
''' load all connectors '''
|
||||||
return get_connector(self=True)
|
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 '''
|
''' pick a book data connector '''
|
||||||
if book and book.connector:
|
if book and book.connector:
|
||||||
connector_info = book.connector
|
connector_info = book.connector
|
||||||
elif self:
|
|
||||||
connector_info = models.Connector.objects.filter(
|
|
||||||
connector_file='self_connector'
|
|
||||||
).first()
|
|
||||||
else:
|
else:
|
||||||
# only select from external connectors
|
# only select from external connectors
|
||||||
connector_info = models.Connector.objects.exclude(
|
connector_info = models.Connector.objects.filter(
|
||||||
connector_file='self_connector'
|
self=False
|
||||||
).first()
|
).order_by('priority').first()
|
||||||
|
return load_connector(connector_info)
|
||||||
|
|
||||||
|
|
||||||
|
def load_connector(connector_info):
|
||||||
|
''' instantiate the connector class '''
|
||||||
connector = importlib.import_module(
|
connector = importlib.import_module(
|
||||||
'fedireads.connectors.%s' % connector_info.connector_file
|
'fedireads.connectors.%s' % connector_info.connector_file
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,11 +14,14 @@ class AbstractConnector(ABC):
|
||||||
info = models.Connector.objects.get(identifier=identifier)
|
info = models.Connector.objects.get(identifier=identifier)
|
||||||
self.connector = info
|
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.covers_url = info.covers_url
|
||||||
self.search_url = info.search_url
|
self.search_url = info.search_url
|
||||||
self.key_name = info.key_name
|
self.key_name = info.key_name
|
||||||
self.max_query_count = info.max_query_count
|
self.max_query_count = info.max_query_count
|
||||||
|
self.name = info.name
|
||||||
|
self.self = info.self
|
||||||
|
|
||||||
|
|
||||||
def is_available(self):
|
def is_available(self):
|
||||||
|
|
39
fedireads/migrations/0036_auto_20200503_1952.py
Normal file
39
fedireads/migrations/0036_auto_20200503_1952.py
Normal file
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -16,14 +16,17 @@ ConnectorFiles = models.TextChoices('ConnectorFiles', CONNECTORS)
|
||||||
class Connector(FedireadsModel):
|
class Connector(FedireadsModel):
|
||||||
''' book data source connectors '''
|
''' book data source connectors '''
|
||||||
identifier = models.CharField(max_length=255, unique=True)
|
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(
|
connector_file = models.CharField(
|
||||||
max_length=255,
|
max_length=255,
|
||||||
default='openlibrary',
|
|
||||||
choices=ConnectorFiles.choices
|
choices=ConnectorFiles.choices
|
||||||
)
|
)
|
||||||
api_key = models.CharField(max_length=255, null=True)
|
api_key = models.CharField(max_length=255, null=True)
|
||||||
|
|
||||||
base_url = models.CharField(max_length=255)
|
base_url = models.CharField(max_length=255)
|
||||||
|
books_url = models.CharField(max_length=255)
|
||||||
covers_url = models.CharField(max_length=255)
|
covers_url = models.CharField(max_length=255)
|
||||||
search_url = models.CharField(max_length=255, null=True)
|
search_url = models.CharField(max_length=255, null=True)
|
||||||
|
|
||||||
|
|
|
@ -67,9 +67,9 @@ class ImportItem(models.Model):
|
||||||
|
|
||||||
def get_book_from_isbn(self):
|
def get_book_from_isbn(self):
|
||||||
''' search by isbn '''
|
''' search by isbn '''
|
||||||
search_results = books_manager.search(self.isbn)
|
search_result = books_manager.search(self.isbn, first=True)
|
||||||
if search_results:
|
if search_result:
|
||||||
return books_manager.get_or_create_book(search_results[0].key)
|
return books_manager.get_or_create_book(search_result.key)
|
||||||
|
|
||||||
def get_book_from_title_author(self):
|
def get_book_from_title_author(self):
|
||||||
''' search by title and author '''
|
''' search by title and author '''
|
||||||
|
@ -77,9 +77,9 @@ class ImportItem(models.Model):
|
||||||
self.data['Title'],
|
self.data['Title'],
|
||||||
self.data['Author']
|
self.data['Author']
|
||||||
)
|
)
|
||||||
search_results = books_manager.search(search_term)
|
search_result = books_manager.search(search_term, first=True)
|
||||||
if search_results:
|
if search_result:
|
||||||
return books_manager.get_or_create_book(search_results[0].key)
|
return books_manager.get_or_create_book(search_result.key)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def isbn(self):
|
def isbn(self):
|
||||||
|
|
|
@ -45,6 +45,10 @@ h3 small {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* fixed display top bar */
|
/* fixed display top bar */
|
||||||
body {
|
body {
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="content">
|
<div class="content-container">
|
||||||
<div>
|
<h2>Search results</h2>
|
||||||
<h1>Search results</h1>
|
{% for result_set in results %}
|
||||||
{% for result in results %}
|
<section>
|
||||||
|
{% if not result_set.connector.self %}
|
||||||
|
<h3>
|
||||||
|
Results from <a href="{{ result_set.connector.base_url }}">{{ result_set.connector.name }}</a>
|
||||||
|
</h3>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for result in result_set.results %}
|
||||||
<div>
|
<div>
|
||||||
<a href="/book/{{ result.key }}">{{ result.title }}</a> by {{ result.author }} ({{ result.year }})
|
<a href="/book/{{ result.key }}" target="_blank">{{ result.title }}</a> by {{ result.author }} ({{ result.year }})
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</section>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -13,8 +13,10 @@ User.objects.get(id=1).followers.add(User.objects.get(id=2))
|
||||||
|
|
||||||
Connector.objects.create(
|
Connector.objects.create(
|
||||||
identifier='openlibrary.org',
|
identifier='openlibrary.org',
|
||||||
|
name='OpenLibrary',
|
||||||
connector_file='openlibrary',
|
connector_file='openlibrary',
|
||||||
base_url='https://openlibrary.org',
|
base_url='https://openlibrary.org',
|
||||||
|
books_url='https://openlibrary.org',
|
||||||
covers_url='https://covers.openlibrary.org',
|
covers_url='https://covers.openlibrary.org',
|
||||||
search_url='https://openlibrary.org/search?q=',
|
search_url='https://openlibrary.org/search?q=',
|
||||||
key_name='openlibrary_key',
|
key_name='openlibrary_key',
|
||||||
|
@ -22,11 +24,15 @@ Connector.objects.create(
|
||||||
|
|
||||||
Connector.objects.create(
|
Connector.objects.create(
|
||||||
identifier=DOMAIN,
|
identifier=DOMAIN,
|
||||||
|
name='Local',
|
||||||
|
self=True,
|
||||||
connector_file='self_connector',
|
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,
|
covers_url='https://%s/images/covers' % DOMAIN,
|
||||||
search_url='https://%s/search?q=' % DOMAIN,
|
search_url='https://%s/search?q=' % DOMAIN,
|
||||||
key_name='openlibrary_key',
|
key_name='openlibrary_key',
|
||||||
|
priority=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue