2022-09-09 17:46:55 +00:00
|
|
|
from django.db.models import prefetch_related_objects
|
2024-06-18 21:07:14 +00:00
|
|
|
from django.templatetags.static import static
|
2020-09-27 07:34:56 +00:00
|
|
|
from rest_framework import serializers
|
2022-09-09 17:46:55 +00:00
|
|
|
from rest_framework.serializers import ListSerializer
|
2020-09-27 07:34:56 +00:00
|
|
|
|
2023-10-01 19:57:32 +00:00
|
|
|
from bookmarks.models import Bookmark, Tag, build_tag_string, UserProfile
|
2020-09-27 07:34:56 +00:00
|
|
|
from bookmarks.services.bookmarks import create_bookmark, update_bookmark
|
|
|
|
from bookmarks.services.tags import get_or_create_tag
|
|
|
|
|
|
|
|
|
|
|
|
class TagListField(serializers.ListField):
|
|
|
|
child = serializers.CharField()
|
|
|
|
|
|
|
|
|
2022-09-09 17:46:55 +00:00
|
|
|
class BookmarkListSerializer(ListSerializer):
|
|
|
|
def to_representation(self, data):
|
|
|
|
# Prefetch nested relations to avoid n+1 queries
|
2024-01-27 10:29:16 +00:00
|
|
|
prefetch_related_objects(data, "tags")
|
2022-09-09 17:46:55 +00:00
|
|
|
|
|
|
|
return super().to_representation(data)
|
|
|
|
|
|
|
|
|
2020-09-27 07:34:56 +00:00
|
|
|
class BookmarkSerializer(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
|
|
model = Bookmark
|
2020-12-31 08:47:51 +00:00
|
|
|
fields = [
|
2024-01-27 10:29:16 +00:00
|
|
|
"id",
|
|
|
|
"url",
|
|
|
|
"title",
|
|
|
|
"description",
|
|
|
|
"notes",
|
|
|
|
"website_title",
|
|
|
|
"website_description",
|
2024-03-17 09:04:05 +00:00
|
|
|
"web_archive_snapshot_url",
|
2024-06-18 21:07:14 +00:00
|
|
|
"favicon_url",
|
|
|
|
"preview_image_url",
|
2024-01-27 10:29:16 +00:00
|
|
|
"is_archived",
|
|
|
|
"unread",
|
|
|
|
"shared",
|
|
|
|
"tag_names",
|
|
|
|
"date_added",
|
|
|
|
"date_modified",
|
2020-12-31 08:47:51 +00:00
|
|
|
]
|
|
|
|
read_only_fields = [
|
2024-01-27 10:29:16 +00:00
|
|
|
"website_title",
|
|
|
|
"website_description",
|
2024-03-17 09:04:05 +00:00
|
|
|
"web_archive_snapshot_url",
|
2024-06-18 21:07:14 +00:00
|
|
|
"favicon_url",
|
|
|
|
"preview_image_url",
|
2024-01-27 10:29:16 +00:00
|
|
|
"date_added",
|
|
|
|
"date_modified",
|
2020-12-31 08:47:51 +00:00
|
|
|
]
|
2022-09-09 17:46:55 +00:00
|
|
|
list_serializer_class = BookmarkListSerializer
|
2020-09-27 07:34:56 +00:00
|
|
|
|
2021-02-18 21:02:45 +00:00
|
|
|
# Override optional char fields to provide default value
|
2024-01-27 10:29:16 +00:00
|
|
|
title = serializers.CharField(required=False, allow_blank=True, default="")
|
|
|
|
description = serializers.CharField(required=False, allow_blank=True, default="")
|
|
|
|
notes = serializers.CharField(required=False, allow_blank=True, default="")
|
2022-05-26 02:10:36 +00:00
|
|
|
is_archived = serializers.BooleanField(required=False, default=False)
|
2022-07-23 20:17:20 +00:00
|
|
|
unread = serializers.BooleanField(required=False, default=False)
|
2022-08-04 17:37:16 +00:00
|
|
|
shared = serializers.BooleanField(required=False, default=False)
|
2020-09-27 07:34:56 +00:00
|
|
|
# Override readonly tag_names property to allow passing a list of tag names to create/update
|
2021-02-18 21:02:45 +00:00
|
|
|
tag_names = TagListField(required=False, default=[])
|
2024-06-18 21:07:14 +00:00
|
|
|
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
|
2020-09-27 07:34:56 +00:00
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
bookmark = Bookmark()
|
2024-01-27 10:29:16 +00:00
|
|
|
bookmark.url = validated_data["url"]
|
|
|
|
bookmark.title = validated_data["title"]
|
|
|
|
bookmark.description = validated_data["description"]
|
|
|
|
bookmark.notes = validated_data["notes"]
|
|
|
|
bookmark.is_archived = validated_data["is_archived"]
|
|
|
|
bookmark.unread = validated_data["unread"]
|
|
|
|
bookmark.shared = validated_data["shared"]
|
|
|
|
tag_string = build_tag_string(validated_data["tag_names"])
|
|
|
|
return create_bookmark(bookmark, tag_string, self.context["user"])
|
2020-09-27 07:34:56 +00:00
|
|
|
|
|
|
|
def update(self, instance: Bookmark, validated_data):
|
2022-05-26 02:15:13 +00:00
|
|
|
# Update fields if they were provided in the payload
|
2024-01-27 10:29:16 +00:00
|
|
|
for key in ["url", "title", "description", "notes", "unread", "shared"]:
|
2022-05-26 02:15:13 +00:00
|
|
|
if key in validated_data:
|
|
|
|
setattr(instance, key, validated_data[key])
|
|
|
|
|
|
|
|
# Use tag string from payload, or use bookmark's current tags as fallback
|
|
|
|
tag_string = build_tag_string(instance.tag_names)
|
2024-01-27 10:29:16 +00:00
|
|
|
if "tag_names" in validated_data:
|
|
|
|
tag_string = build_tag_string(validated_data["tag_names"])
|
2022-05-26 02:15:13 +00:00
|
|
|
|
2024-01-27 10:29:16 +00:00
|
|
|
return update_bookmark(instance, tag_string, self.context["user"])
|
2020-09-27 07:34:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TagSerializer(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
|
|
model = Tag
|
2024-01-27 10:29:16 +00:00
|
|
|
fields = ["id", "name", "date_added"]
|
|
|
|
read_only_fields = ["date_added"]
|
2020-09-27 07:34:56 +00:00
|
|
|
|
|
|
|
def create(self, validated_data):
|
2024-01-27 10:29:16 +00:00
|
|
|
return get_or_create_tag(validated_data["name"], self.context["user"])
|
2023-10-01 19:57:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
class UserProfileSerializer(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
|
|
model = UserProfile
|
|
|
|
fields = [
|
|
|
|
"theme",
|
|
|
|
"bookmark_date_display",
|
|
|
|
"bookmark_link_target",
|
|
|
|
"web_archive_integration",
|
|
|
|
"tag_search",
|
|
|
|
"enable_sharing",
|
|
|
|
"enable_public_sharing",
|
|
|
|
"enable_favicons",
|
|
|
|
"display_url",
|
|
|
|
"permanent_notes",
|
|
|
|
"search_preferences",
|
|
|
|
]
|