mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-16 05:41:36 +00:00
Rename local key and suggest fedireads connectors
This commit is contained in:
parent
0f98610629
commit
ed6fd6d48e
14 changed files with 74 additions and 42 deletions
|
@ -2,14 +2,13 @@
|
||||||
import importlib
|
import importlib
|
||||||
|
|
||||||
from fedireads import models
|
from fedireads import models
|
||||||
from fedireads.connectors.settings import CONNECTORS
|
|
||||||
|
|
||||||
|
|
||||||
def get_or_create_book(key):
|
def get_or_create_book(key):
|
||||||
''' pull up a book record by whatever means possible '''
|
''' pull up a book record by whatever means possible '''
|
||||||
try:
|
try:
|
||||||
book = models.Book.objects.select_subclasses().get(
|
book = models.Book.objects.select_subclasses().get(
|
||||||
local_key=key
|
fedireads_key=key
|
||||||
)
|
)
|
||||||
return book
|
return book
|
||||||
except models.Book.DoesNotExist:
|
except models.Book.DoesNotExist:
|
||||||
|
@ -32,6 +31,7 @@ def get_connector(book=None):
|
||||||
else:
|
else:
|
||||||
connector_info = models.Connector.objects.first()
|
connector_info = models.Connector.objects.first()
|
||||||
|
|
||||||
classname = CONNECTORS[connector_info.name]['classname']
|
connector = importlib.import_module(
|
||||||
connector = importlib.import_module(classname)
|
'fedireads.connectors.%s' % connector_info.connector_file
|
||||||
return connector.Connector()
|
)
|
||||||
|
return connector.Connector(connector_info.identifier)
|
||||||
|
|
|
@ -2,19 +2,14 @@
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
from fedireads import models
|
from fedireads import models
|
||||||
from fedireads.connectors import CONNECTORS
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractConnector(ABC):
|
class AbstractConnector(ABC):
|
||||||
''' generic book data connector '''
|
''' generic book data connector '''
|
||||||
|
|
||||||
def __init__(self, connector_name):
|
def __init__(self, identifier):
|
||||||
# load connector settings
|
# load connector settings
|
||||||
settings = CONNECTORS.get(connector_name)
|
info = models.Connector.objects.get(identifier=identifier)
|
||||||
if not settings:
|
|
||||||
raise ValueError('No connector with name "%s"' % connector_name)
|
|
||||||
|
|
||||||
info = models.Connector.objects.get(name=settings['db_name'])
|
|
||||||
self.model = info
|
self.model = info
|
||||||
|
|
||||||
self.url = info.base_url
|
self.url = info.base_url
|
||||||
|
|
|
@ -10,8 +10,8 @@ from .abstract_connector import AbstractConnector, SearchResult
|
||||||
|
|
||||||
class Connector(AbstractConnector):
|
class Connector(AbstractConnector):
|
||||||
''' instantiate a connector for OL '''
|
''' instantiate a connector for OL '''
|
||||||
def __init__(self):
|
def __init__(self, identifier):
|
||||||
super().__init__('OpenLibrary')
|
super().__init__(identifier)
|
||||||
|
|
||||||
|
|
||||||
def search(self, query):
|
def search(self, query):
|
||||||
|
@ -140,3 +140,4 @@ class Connector(AbstractConnector):
|
||||||
|
|
||||||
def update_book(self, book_obj):
|
def update_book(self, book_obj):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
''' settings book data connectors '''
|
''' settings book data connectors '''
|
||||||
CONNECTORS = {
|
|
||||||
'OpenLibrary': {
|
CONNECTORS = ['openlibrary', 'fedireads']
|
||||||
'db_name': 'OpenLibrary',
|
|
||||||
'classname': 'fedireads.connectors.openlibrary',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Generated by Django 3.0.3 on 2020-03-27 22:36
|
# Generated by Django 3.0.3 on 2020-03-27 23:35
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
import fedireads.models.book
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -17,20 +18,24 @@ class Migration(migrations.Migration):
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('created_date', models.DateTimeField(auto_now_add=True)),
|
('created_date', models.DateTimeField(auto_now_add=True)),
|
||||||
('updated_date', models.DateTimeField(auto_now=True)),
|
('updated_date', models.DateTimeField(auto_now=True)),
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
('identifier', models.CharField(max_length=255, unique=True)),
|
||||||
|
('connector_file', models.CharField(choices=[('openlibrary', 'Openlibrary'), ('fedireads', 'Fedireads')], default='openlibrary', max_length=255)),
|
||||||
|
('is_self', models.BooleanField(default=False)),
|
||||||
('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)),
|
||||||
('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)),
|
||||||
('key_name', models.CharField(max_length=255, unique=True)),
|
('key_name', models.CharField(max_length=255)),
|
||||||
('politeness_delay', models.IntegerField(null=True)),
|
('politeness_delay', models.IntegerField(null=True)),
|
||||||
('max_query_count', models.IntegerField(null=True)),
|
('max_query_count', models.IntegerField(null=True)),
|
||||||
('query_count', models.IntegerField(default=0)),
|
('query_count', models.IntegerField(default=0)),
|
||||||
('query_count_expiry', models.DateTimeField(auto_now_add=True)),
|
('query_count_expiry', models.DateTimeField(auto_now_add=True)),
|
||||||
],
|
],
|
||||||
options={
|
),
|
||||||
'abstract': False,
|
migrations.RenameField(
|
||||||
},
|
model_name='book',
|
||||||
|
old_name='local_key',
|
||||||
|
new_name='fedireads_key',
|
||||||
),
|
),
|
||||||
migrations.RenameField(
|
migrations.RenameField(
|
||||||
model_name='book',
|
model_name='book',
|
||||||
|
@ -41,6 +46,10 @@ class Migration(migrations.Migration):
|
||||||
model_name='book',
|
model_name='book',
|
||||||
name='local_edits',
|
name='local_edits',
|
||||||
),
|
),
|
||||||
|
migrations.AddConstraint(
|
||||||
|
model_name='connector',
|
||||||
|
constraint=models.CheckConstraint(check=models.Q(connector_file__in=fedireads.models.book.ConnectorFiles), name='connector_file_valid'),
|
||||||
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='book',
|
model_name='book',
|
||||||
name='connector',
|
name='connector',
|
|
@ -8,17 +8,28 @@ from fedireads.settings import DOMAIN
|
||||||
from fedireads.utils.fields import JSONField, ArrayField
|
from fedireads.utils.fields import JSONField, ArrayField
|
||||||
from fedireads.utils.models import FedireadsModel
|
from fedireads.utils.models import FedireadsModel
|
||||||
|
|
||||||
|
from fedireads.connectors.settings import CONNECTORS
|
||||||
|
|
||||||
|
|
||||||
|
ConnectorFiles = models.TextChoices('ConnectorFiles', CONNECTORS)
|
||||||
class Connector(FedireadsModel):
|
class Connector(FedireadsModel):
|
||||||
''' book data source connectors '''
|
''' book data source connectors '''
|
||||||
name = models.CharField(max_length=255, unique=True)
|
identifier = models.CharField(max_length=255, unique=True)
|
||||||
|
connector_file = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
default='openlibrary',
|
||||||
|
choices=ConnectorFiles.choices
|
||||||
|
)
|
||||||
|
# is this a connector to your own database, should only be true if
|
||||||
|
# the connector_file is `fedireads`
|
||||||
|
is_self = models.BooleanField(default=False)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
key_name = models.CharField(max_length=255, unique=True)
|
key_name = models.CharField(max_length=255)
|
||||||
|
|
||||||
politeness_delay = models.IntegerField(null=True) #seconds
|
politeness_delay = models.IntegerField(null=True) #seconds
|
||||||
max_query_count = models.IntegerField(null=True)
|
max_query_count = models.IntegerField(null=True)
|
||||||
|
@ -27,13 +38,21 @@ class Connector(FedireadsModel):
|
||||||
# when to reset the query count back to 0 (ie, after 1 day)
|
# when to reset the query count back to 0 (ie, after 1 day)
|
||||||
query_count_expiry = models.DateTimeField(auto_now_add=True)
|
query_count_expiry = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
constraints = [
|
||||||
|
models.CheckConstraint(
|
||||||
|
check=models.Q(connector_file__in=ConnectorFiles),
|
||||||
|
name='connector_file_valid'
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Book(FedireadsModel):
|
class Book(FedireadsModel):
|
||||||
''' a generic book, which can mean either an edition or a work '''
|
''' a generic book, which can mean either an edition or a work '''
|
||||||
# these identifiers apply to both works and editions
|
# these identifiers apply to both works and editions
|
||||||
openlibrary_key = models.CharField(max_length=255, unique=True, null=True)
|
openlibrary_key = models.CharField(max_length=255, unique=True, null=True)
|
||||||
librarything_key = models.CharField(max_length=255, unique=True, null=True)
|
librarything_key = models.CharField(max_length=255, unique=True, null=True)
|
||||||
local_key = models.CharField(max_length=255, unique=True, default=uuid4)
|
fedireads_key = models.CharField(max_length=255, unique=True, default=uuid4)
|
||||||
misc_identifiers = JSONField(null=True)
|
misc_identifiers = JSONField(null=True)
|
||||||
|
|
||||||
# info about where the data comes from and where/if to sync
|
# info about where the data comes from and where/if to sync
|
||||||
|
|
|
@ -232,7 +232,7 @@ def handle_tag(user, book, name):
|
||||||
|
|
||||||
def handle_untag(user, book, name):
|
def handle_untag(user, book, name):
|
||||||
''' tag a book '''
|
''' tag a book '''
|
||||||
book = models.Book.objects.get(local_key=book)
|
book = models.Book.objects.get(fedireads_key=book)
|
||||||
tag = models.Tag.objects.get(name=name, book=book, user=user)
|
tag = models.Tag.objects.get(name=name, book=book, user=user)
|
||||||
tag_activity = activitypub.get_remove_tag(tag)
|
tag_activity = activitypub.get_remove_tag(tag)
|
||||||
tag.delete()
|
tag.delete()
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<h2><q>{{ book.title }}</q> by
|
<h2><q>{{ book.title }}</q> by
|
||||||
{% include 'snippets/authors.html' with book=book %}</h2>
|
{% include 'snippets/authors.html' with book=book %}</h2>
|
||||||
<div>
|
<div>
|
||||||
{% if book.parent_work %}<p>Edition of <a href="/book/{{ book.parent_work.local_key }}">{{ book.parent_work.title }}</a></p>{% endif %}
|
{% if book.parent_work %}<p>Edition of <a href="/book/{{ book.parent_work.fedireads_key }}">{{ book.parent_work.title }}</a></p>{% endif %}
|
||||||
<div class="book-preview">
|
<div class="book-preview">
|
||||||
|
|
||||||
{% include 'snippets/book_cover.html' with book=book size=large %}
|
{% include 'snippets/book_cover.html' with book=book size=large %}
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
<h2>Leave a review</h2>
|
<h2>Leave a review</h2>
|
||||||
<form class="review-form" name="review" action="/review/" method="post">
|
<form class="review-form" name="review" action="/review/" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="book" value="{{ book.local_key }}"></input>
|
<input type="hidden" name="book" value="{{ book.fedireads_key }}"></input>
|
||||||
{{ review_form.as_p }}
|
{{ review_form.as_p }}
|
||||||
<button type="submit">Post review</button>
|
<button type="submit">Post review</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<a href="/author/{{ book.authors.first.local_key }}" class="author">{{ book.authors.first.name }}</a>
|
<a href="/author/{{ book.authors.first.fedireads_key }}" class="author">{{ book.authors.first.name }}</a>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% load fr_display %}
|
{% load fr_display %}
|
||||||
{% include 'snippets/book_cover.html' with book=book %}
|
{% include 'snippets/book_cover.html' with book=book %}
|
||||||
<p class="title">
|
<p class="title">
|
||||||
<a href="/book/{{ book.local_key }}">{{ book.title }}</a>
|
<a href="/book/{{ book.fedireads_key }}">{{ book.title }}</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
by {% include 'snippets/authors.html' with book=book %}
|
by {% include 'snippets/authors.html' with book=book %}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<h2>
|
<h2>
|
||||||
{% include 'snippets/avatar.html' with user=user %}
|
{% include 'snippets/avatar.html' with user=user %}
|
||||||
Your thoughts on
|
Your thoughts on
|
||||||
<a href="/book/{{ book.local_key }}">{{ book.title }}</a>
|
<a href="/book/{{ book.fedireads_key }}">{{ book.title }}</a>
|
||||||
by {% include 'snippets/authors.html' with book=book %}
|
by {% include 'snippets/authors.html' with book=book %}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
@ -24,14 +24,14 @@
|
||||||
{% include 'snippets/book_cover.html' with book=book %}
|
{% include 'snippets/book_cover.html' with book=book %}
|
||||||
<form class="tab-option-{{ book.id }} review-form" name="review" action="/review/" method="post" id="tab-review-{{ book.id }}">
|
<form class="tab-option-{{ book.id }} review-form" name="review" action="/review/" method="post" id="tab-review-{{ book.id }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="book" value="{{ book.local_key }}"></input>
|
<input type="hidden" name="book" value="{{ book.fedireads_key }}"></input>
|
||||||
{{ review_form.as_p }}
|
{{ review_form.as_p }}
|
||||||
<button type="submit">post review</button>
|
<button type="submit">post review</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form class="hidden tab-option-{{ book.id }} review-form" name="comment" action="/comment/" method="post" id="tab-comment-{{ book.id }}">
|
<form class="hidden tab-option-{{ book.id }} review-form" name="comment" action="/comment/" method="post" id="tab-comment-{{ book.id }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="book" value="{{ book.local_key }}"></input>
|
<input type="hidden" name="book" value="{{ book.fedireads_key }}"></input>
|
||||||
{{ comment_form.as_p }}
|
{{ comment_form.as_p }}
|
||||||
<button type="submit">post comment</button>
|
<button type="submit">post comment</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
{% include 'snippets/book_cover.html' with book=book size="small" %}
|
{% include 'snippets/book_cover.html' with book=book size="small" %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/book/{{ book.local_key }}">{{ book.title }}</a>
|
<a href="/book/{{ book.fedireads_key }}">{{ book.title }}</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ book.authors.first.name }}
|
{{ book.authors.first.name }}
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
{% if tag.identifier in user_tags %}
|
{% if tag.identifier in user_tags %}
|
||||||
<form class="tag-form" name="tag" action="/untag/" method="post">
|
<form class="tag-form" name="tag" action="/untag/" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="book" value="{{ book.local_key }}"></input>
|
<input type="hidden" name="book" value="{{ book.fedireads_key }}"></input>
|
||||||
<input type="hidden" name="name" value="{{ tag.name }}"></input>
|
<input type="hidden" name="name" value="{{ tag.name }}"></input>
|
||||||
<button type="submit">x</button>
|
<button type="submit">x</button>
|
||||||
</form>
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<form class="tag-form" name="tag" action="/tag/" method="post">
|
<form class="tag-form" name="tag" action="/tag/" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="book" value="{{ book.local_key }}"></input>
|
<input type="hidden" name="book" value="{{ book.fedireads_key }}"></input>
|
||||||
<input type="hidden" name="name" value="{{ tag.name }}"></input>
|
<input type="hidden" name="name" value="{{ tag.name }}"></input>
|
||||||
<button type="submit">+</button>
|
<button type="submit">+</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
16
init_db.py
16
init_db.py
|
@ -1,6 +1,7 @@
|
||||||
''' starter data '''
|
''' starter data '''
|
||||||
from fedireads.models import Connector, User
|
|
||||||
from fedireads.books_manager import get_or_create_book
|
from fedireads.books_manager import get_or_create_book
|
||||||
|
from fedireads.models import Connector, User
|
||||||
|
from fedireads.settings import DOMAIN
|
||||||
|
|
||||||
User.objects.create_user('mouse', 'mouse.reeve@gmail.com', 'password123')
|
User.objects.create_user('mouse', 'mouse.reeve@gmail.com', 'password123')
|
||||||
User.objects.create_user(
|
User.objects.create_user(
|
||||||
|
@ -11,13 +12,24 @@ User.objects.create_user(
|
||||||
User.objects.get(id=1).followers.add(User.objects.get(id=2))
|
User.objects.get(id=1).followers.add(User.objects.get(id=2))
|
||||||
|
|
||||||
Connector.objects.create(
|
Connector.objects.create(
|
||||||
name='OpenLibrary',
|
identifier='openlibrary.org',
|
||||||
|
connector_file='openlibrary',
|
||||||
base_url='https://openlibrary.org',
|
base_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',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Connector.objects.create(
|
||||||
|
identifier=DOMAIN,
|
||||||
|
connector_file='fedireads',
|
||||||
|
base_url='https://%s/book' % DOMAIN,
|
||||||
|
covers_url='https://%s/images/covers' % DOMAIN,
|
||||||
|
search_url='https://%s/search?q=' % DOMAIN,
|
||||||
|
key_name='openlibrary_key',
|
||||||
|
is_self=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
get_or_create_book('OL1715344W')
|
get_or_create_book('OL1715344W')
|
||||||
get_or_create_book('OL102749W')
|
get_or_create_book('OL102749W')
|
||||||
|
|
Loading…
Reference in a new issue