mirror of
https://github.com/sissbruecker/linkding
synced 2024-11-21 19:03:02 +00:00
Include favicons and thumbnails in REST API (#763)
* Include favicons and thumbnails in REST API * Fix serialization for custom endpoints
This commit is contained in:
parent
b28352fb28
commit
380f5ed19c
5 changed files with 100 additions and 6 deletions
|
@ -52,7 +52,7 @@ class BookmarkViewSet(
|
|||
return Bookmark.objects.all().filter(owner=user)
|
||||
|
||||
def get_serializer_context(self):
|
||||
return {"user": self.request.user}
|
||||
return {"request": self.request, "user": self.request.user}
|
||||
|
||||
@action(methods=["get"], detail=False)
|
||||
def archived(self, request):
|
||||
|
@ -60,8 +60,8 @@ class BookmarkViewSet(
|
|||
search = BookmarkSearch.from_request(request.GET)
|
||||
query_set = queries.query_archived_bookmarks(user, user.profile, search)
|
||||
page = self.paginate_queryset(query_set)
|
||||
serializer = self.get_serializer_class()
|
||||
data = serializer(page, many=True).data
|
||||
serializer = self.get_serializer(page, many=True)
|
||||
data = serializer.data
|
||||
return self.get_paginated_response(data)
|
||||
|
||||
@action(methods=["get"], detail=False)
|
||||
|
@ -73,8 +73,8 @@ class BookmarkViewSet(
|
|||
user, request.user_profile, search, public_only
|
||||
)
|
||||
page = self.paginate_queryset(query_set)
|
||||
serializer = self.get_serializer_class()
|
||||
data = serializer(page, many=True).data
|
||||
serializer = self.get_serializer(page, many=True)
|
||||
data = serializer.data
|
||||
return self.get_paginated_response(data)
|
||||
|
||||
@action(methods=["post"], detail=True)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.db.models import prefetch_related_objects
|
||||
from django.templatetags.static import static
|
||||
from rest_framework import serializers
|
||||
from rest_framework.serializers import ListSerializer
|
||||
|
||||
|
@ -31,6 +32,8 @@ class BookmarkSerializer(serializers.ModelSerializer):
|
|||
"website_title",
|
||||
"website_description",
|
||||
"web_archive_snapshot_url",
|
||||
"favicon_url",
|
||||
"preview_image_url",
|
||||
"is_archived",
|
||||
"unread",
|
||||
"shared",
|
||||
|
@ -42,6 +45,8 @@ class BookmarkSerializer(serializers.ModelSerializer):
|
|||
"website_title",
|
||||
"website_description",
|
||||
"web_archive_snapshot_url",
|
||||
"favicon_url",
|
||||
"preview_image_url",
|
||||
"date_added",
|
||||
"date_modified",
|
||||
]
|
||||
|
@ -56,6 +61,24 @@ class BookmarkSerializer(serializers.ModelSerializer):
|
|||
shared = serializers.BooleanField(required=False, default=False)
|
||||
# Override readonly tag_names property to allow passing a list of tag names to create/update
|
||||
tag_names = TagListField(required=False, default=[])
|
||||
favicon_url = serializers.SerializerMethodField()
|
||||
preview_image_url = serializers.SerializerMethodField()
|
||||
|
||||
def get_favicon_url(self, obj: Bookmark):
|
||||
if not obj.favicon_file:
|
||||
return None
|
||||
request = self.context.get("request")
|
||||
favicon_file_path = static(obj.favicon_file)
|
||||
favicon_url = request.build_absolute_uri(favicon_file_path)
|
||||
return favicon_url
|
||||
|
||||
def get_preview_image_url(self, obj: Bookmark):
|
||||
if not obj.preview_image_file:
|
||||
return None
|
||||
request = self.context.get("request")
|
||||
preview_image_file_path = static(obj.preview_image_file)
|
||||
preview_image_url = request.build_absolute_uri(preview_image_file_path)
|
||||
return preview_image_url
|
||||
|
||||
def create(self, validated_data):
|
||||
bookmark = Bookmark()
|
||||
|
|
|
@ -87,6 +87,8 @@ class BookmarkFactoryMixin:
|
|||
shared: bool = False,
|
||||
with_tags: bool = False,
|
||||
with_web_archive_snapshot_url: bool = False,
|
||||
with_favicon_file: bool = False,
|
||||
with_preview_image_file: bool = False,
|
||||
user: User = None,
|
||||
):
|
||||
user = user or self.get_or_create_test_user()
|
||||
|
@ -118,6 +120,12 @@ class BookmarkFactoryMixin:
|
|||
web_archive_snapshot_url = ""
|
||||
if with_web_archive_snapshot_url:
|
||||
web_archive_snapshot_url = f"https://web.archive.org/web/{i}"
|
||||
favicon_file = ""
|
||||
if with_favicon_file:
|
||||
favicon_file = f"favicon_{i}.png"
|
||||
preview_image_file = ""
|
||||
if with_preview_image_file:
|
||||
preview_image_file = f"preview_image_{i}.png"
|
||||
bookmark = self.setup_bookmark(
|
||||
url=url,
|
||||
title=title,
|
||||
|
@ -126,6 +134,8 @@ class BookmarkFactoryMixin:
|
|||
shared=shared,
|
||||
tags=tags,
|
||||
web_archive_snapshot_url=web_archive_snapshot_url,
|
||||
favicon_file=favicon_file,
|
||||
preview_image_file=preview_image_file,
|
||||
user=user,
|
||||
)
|
||||
bookmarks.append(bookmark)
|
||||
|
|
|
@ -36,6 +36,16 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin):
|
|||
expectation["website_title"] = bookmark.website_title
|
||||
expectation["website_description"] = bookmark.website_description
|
||||
expectation["web_archive_snapshot_url"] = bookmark.web_archive_snapshot_url
|
||||
expectation["favicon_url"] = (
|
||||
f"http://testserver/static/{bookmark.favicon_file}"
|
||||
if bookmark.favicon_file
|
||||
else None
|
||||
)
|
||||
expectation["preview_image_url"] = (
|
||||
f"http://testserver/static/{bookmark.preview_image_file}"
|
||||
if bookmark.preview_image_file
|
||||
else None
|
||||
)
|
||||
expectation["is_archived"] = bookmark.is_archived
|
||||
expectation["unread"] = bookmark.unread
|
||||
expectation["shared"] = bookmark.shared
|
||||
|
@ -65,7 +75,11 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin):
|
|||
def test_list_bookmarks_with_more_details(self):
|
||||
self.authenticate()
|
||||
bookmarks = self.setup_numbered_bookmarks(
|
||||
5, with_tags=True, with_web_archive_snapshot_url=True
|
||||
5,
|
||||
with_tags=True,
|
||||
with_web_archive_snapshot_url=True,
|
||||
with_favicon_file=True,
|
||||
with_preview_image_file=True,
|
||||
)
|
||||
|
||||
response = self.get(
|
||||
|
@ -171,6 +185,23 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin):
|
|||
)
|
||||
self.assertBookmarkListEqual(response.data["results"], archived_bookmarks)
|
||||
|
||||
def test_list_archived_bookmarks_with_more_details(self):
|
||||
self.authenticate()
|
||||
archived_bookmarks = self.setup_numbered_bookmarks(
|
||||
5,
|
||||
archived=True,
|
||||
with_tags=True,
|
||||
with_web_archive_snapshot_url=True,
|
||||
with_favicon_file=True,
|
||||
with_preview_image_file=True,
|
||||
)
|
||||
|
||||
response = self.get(
|
||||
reverse("bookmarks:bookmark-archived"),
|
||||
expected_status_code=status.HTTP_200_OK,
|
||||
)
|
||||
self.assertBookmarkListEqual(response.data["results"], archived_bookmarks)
|
||||
|
||||
def test_list_archived_bookmarks_should_filter_by_query(self):
|
||||
self.authenticate()
|
||||
search_value = self.get_random_string()
|
||||
|
@ -220,6 +251,26 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin):
|
|||
)
|
||||
self.assertBookmarkListEqual(response.data["results"], shared_bookmarks)
|
||||
|
||||
def test_list_shared_bookmarks_with_more_details(self):
|
||||
self.authenticate()
|
||||
|
||||
other_user = self.setup_user(enable_sharing=True)
|
||||
shared_bookmarks = self.setup_numbered_bookmarks(
|
||||
5,
|
||||
shared=True,
|
||||
user=other_user,
|
||||
with_tags=True,
|
||||
with_web_archive_snapshot_url=True,
|
||||
with_favicon_file=True,
|
||||
with_preview_image_file=True,
|
||||
)
|
||||
|
||||
response = self.get(
|
||||
reverse("bookmarks:bookmark-shared"),
|
||||
expected_status_code=status.HTTP_200_OK,
|
||||
)
|
||||
self.assertBookmarkListEqual(response.data["results"], shared_bookmarks)
|
||||
|
||||
def test_list_only_publicly_shared_bookmarks_when_not_logged_in(self):
|
||||
user1 = self.setup_user(enable_sharing=True, enable_public_sharing=True)
|
||||
user2 = self.setup_user(enable_sharing=True)
|
||||
|
@ -701,6 +752,8 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin):
|
|||
url="https://example.com",
|
||||
title="Example title",
|
||||
description="Example description",
|
||||
favicon_file="favicon.png",
|
||||
preview_image_file="preview.png",
|
||||
)
|
||||
|
||||
url = reverse("bookmarks:bookmark-check")
|
||||
|
@ -715,6 +768,12 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin):
|
|||
self.assertEqual(bookmark.url, bookmark_data["url"])
|
||||
self.assertEqual(bookmark.title, bookmark_data["title"])
|
||||
self.assertEqual(bookmark.description, bookmark_data["description"])
|
||||
self.assertEqual(
|
||||
"http://testserver/static/favicon.png", bookmark_data["favicon_url"]
|
||||
)
|
||||
self.assertEqual(
|
||||
"http://testserver/static/preview.png", bookmark_data["preview_image_url"]
|
||||
)
|
||||
|
||||
def test_check_returns_existing_metadata_if_url_is_bookmarked(self):
|
||||
self.authenticate()
|
||||
|
|
|
@ -49,6 +49,8 @@ Example response:
|
|||
"website_title": "Website title",
|
||||
"website_description": "Website description",
|
||||
"web_archive_snapshot_url": "https://web.archive.org/web/20200926094623/https://example.com",
|
||||
"favicon_url": "http://127.0.0.1:8000/static/https_example_com.png",
|
||||
"preview_image_url": "http://127.0.0.1:8000/static/0ac5c53db923727765216a3a58e70522.jpg",
|
||||
"is_archived": false,
|
||||
"unread": false,
|
||||
"shared": false,
|
||||
|
|
Loading…
Reference in a new issue