forked from mirrors/bookwyrm
Merge pull request #284 from mouse-reeve/edition_list
Activitypub serializable edition list
This commit is contained in:
commit
eae3b42033
5 changed files with 34 additions and 9 deletions
|
@ -9,8 +9,8 @@ from bookwyrm import activitypub
|
||||||
from bookwyrm.settings import DOMAIN
|
from bookwyrm.settings import DOMAIN
|
||||||
from bookwyrm.utils.fields import ArrayField
|
from bookwyrm.utils.fields import ArrayField
|
||||||
|
|
||||||
from .base_model import ActivityMapping, ActivitypubMixin, BookWyrmModel
|
from .base_model import ActivityMapping, BookWyrmModel
|
||||||
|
from .base_model import ActivitypubMixin, OrderedCollectionPageMixin
|
||||||
|
|
||||||
class Book(ActivitypubMixin, BookWyrmModel):
|
class Book(ActivitypubMixin, BookWyrmModel):
|
||||||
''' a generic book, which can mean either an edition or a work '''
|
''' a generic book, which can mean either an edition or a work '''
|
||||||
|
@ -135,17 +135,32 @@ class Book(ActivitypubMixin, BookWyrmModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Work(Book):
|
class Work(OrderedCollectionPageMixin, Book):
|
||||||
''' a work (an abstract concept of a book that manifests in an edition) '''
|
''' a work (an abstract concept of a book that manifests in an edition) '''
|
||||||
# library of congress catalog control number
|
# library of congress catalog control number
|
||||||
lccn = models.CharField(max_length=255, blank=True, null=True)
|
lccn = models.CharField(max_length=255, blank=True, null=True)
|
||||||
default_edition = models.ForeignKey('Edition', on_delete=models.PROTECT, null=True)
|
# this has to be nullable but should never be null
|
||||||
|
default_edition = models.ForeignKey(
|
||||||
|
'Edition',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def editions_path(self):
|
def editions_path(self):
|
||||||
''' it'd be nice to serialize the edition instead but, recursion '''
|
''' it'd be nice to serialize the edition instead but, recursion '''
|
||||||
return [e.remote_id for e in self.edition_set.all()]
|
return [e.remote_id for e in self.edition_set.all()]
|
||||||
|
|
||||||
|
def to_edition_list(self, **kwargs):
|
||||||
|
''' activitypub serialization for this work's editions '''
|
||||||
|
remote_id = self.local_id + '/editions'
|
||||||
|
return self.to_ordered_collection(
|
||||||
|
self.edition_set,
|
||||||
|
remote_id=remote_id,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
activity_serializer = activitypub.Work
|
activity_serializer = activitypub.Work
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
{% include 'snippets/book_description.html' %}
|
{% include 'snippets/book_description.html' %}
|
||||||
|
|
||||||
{% if book.parent_work.edition_set.count > 1 %}
|
{% if book.parent_work.edition_set.count > 1 %}
|
||||||
<p><a href="/editions/{{ book.parent_work.id }}">{{ book.parent_work.edition_set.count }} editions</a></p>
|
<p><a href="/book/{{ book.parent_work.id }}/editions">{{ book.parent_work.edition_set.count }} editions</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{% if book_results|slice:":1" and local_results.results %}
|
{% if book_results|slice:":1" and local_results.results and request.user.is_authenticated %}
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<p>
|
<p>
|
||||||
Didn't find what you were looking for?
|
Didn't find what you were looking for?
|
||||||
|
|
|
@ -75,7 +75,7 @@ urlpatterns = [
|
||||||
# books
|
# books
|
||||||
re_path(r'%s(.json)?/?$' % book_path, views.book_page),
|
re_path(r'%s(.json)?/?$' % book_path, views.book_page),
|
||||||
re_path(r'%s/edit/?$' % book_path, views.edit_book_page),
|
re_path(r'%s/edit/?$' % book_path, views.edit_book_page),
|
||||||
re_path(r'^editions/(?P<work_id>\d+)/?$', views.editions_page),
|
re_path(r'%s/editions(.json)?/?' % book_path, views.editions_page),
|
||||||
|
|
||||||
re_path(r'^author/(?P<author_id>[\w\-]+)(.json)?/?$', views.author_page),
|
re_path(r'^author/(?P<author_id>[\w\-]+)(.json)?/?$', views.author_page),
|
||||||
# TODO: tag needs a .json path
|
# TODO: tag needs a .json path
|
||||||
|
|
|
@ -559,9 +559,19 @@ def edit_book_page(request, book_id):
|
||||||
return TemplateResponse(request, 'edit_book.html', data)
|
return TemplateResponse(request, 'edit_book.html', data)
|
||||||
|
|
||||||
|
|
||||||
def editions_page(request, work_id):
|
def editions_page(request, book_id):
|
||||||
''' list of editions of a book '''
|
''' list of editions of a book '''
|
||||||
work = models.Work.objects.get(id=work_id)
|
try:
|
||||||
|
work = models.Work.objects.get(id=book_id)
|
||||||
|
except models.Work.DoesNotExist:
|
||||||
|
return HttpResponseNotFound()
|
||||||
|
|
||||||
|
if is_api_request(request):
|
||||||
|
return JsonResponse(
|
||||||
|
work.to_edition_list(**request.GET),
|
||||||
|
encoder=ActivityEncoder
|
||||||
|
)
|
||||||
|
|
||||||
editions = models.Edition.objects.filter(parent_work=work).all()
|
editions = models.Edition.objects.filter(parent_work=work).all()
|
||||||
data = {
|
data = {
|
||||||
'title': 'Editions of %s' % work.title,
|
'title': 'Editions of %s' % work.title,
|
||||||
|
|
Loading…
Reference in a new issue