2022-09-09 17:46:55 +00:00
|
|
|
from django.db.models import prefetch_related_objects
|
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
|
|
|
|
|
|
|
from bookmarks.models import Bookmark, Tag, build_tag_string
|
|
|
|
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
|
|
|
|
prefetch_related_objects(data, 'tags')
|
|
|
|
|
|
|
|
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 = [
|
|
|
|
'id',
|
|
|
|
'url',
|
|
|
|
'title',
|
|
|
|
'description',
|
|
|
|
'website_title',
|
|
|
|
'website_description',
|
2022-05-26 02:10:36 +00:00
|
|
|
'is_archived',
|
2022-07-23 20:17:20 +00:00
|
|
|
'unread',
|
2022-08-04 17:37:16 +00:00
|
|
|
'shared',
|
2020-12-31 08:47:51 +00:00
|
|
|
'tag_names',
|
|
|
|
'date_added',
|
|
|
|
'date_modified'
|
|
|
|
]
|
|
|
|
read_only_fields = [
|
|
|
|
'website_title',
|
|
|
|
'website_description',
|
|
|
|
'date_added',
|
|
|
|
'date_modified'
|
|
|
|
]
|
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
|
|
|
|
title = serializers.CharField(required=False, allow_blank=True, default='')
|
|
|
|
description = 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=[])
|
2020-09-27 07:34:56 +00:00
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
bookmark = Bookmark()
|
|
|
|
bookmark.url = validated_data['url']
|
|
|
|
bookmark.title = validated_data['title']
|
|
|
|
bookmark.description = validated_data['description']
|
2022-05-26 02:10:36 +00:00
|
|
|
bookmark.is_archived = validated_data['is_archived']
|
2022-07-23 20:17:20 +00:00
|
|
|
bookmark.unread = validated_data['unread']
|
2022-08-04 17:37:16 +00:00
|
|
|
bookmark.shared = validated_data['shared']
|
2021-12-12 21:54:22 +00:00
|
|
|
tag_string = build_tag_string(validated_data['tag_names'])
|
2020-09-27 07:34:56 +00:00
|
|
|
return create_bookmark(bookmark, tag_string, self.context['user'])
|
|
|
|
|
|
|
|
def update(self, instance: Bookmark, validated_data):
|
2022-05-26 02:15:13 +00:00
|
|
|
# Update fields if they were provided in the payload
|
2022-08-04 17:37:16 +00:00
|
|
|
for key in ['url', 'title', 'description', '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)
|
|
|
|
if 'tag_names' in validated_data:
|
|
|
|
tag_string = build_tag_string(validated_data['tag_names'])
|
|
|
|
|
2020-09-27 07:34:56 +00:00
|
|
|
return update_bookmark(instance, tag_string, self.context['user'])
|
|
|
|
|
|
|
|
|
|
|
|
class TagSerializer(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
|
|
model = Tag
|
|
|
|
fields = ['id', 'name', 'date_added']
|
|
|
|
read_only_fields = ['date_added']
|
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
return get_or_create_tag(validated_data['name'], self.context['user'])
|