pulseapi/profiles/serializers/profile_entries.py (103 lines of code) (raw):
from django.db.models import Q, Prefetch
from rest_framework import serializers
from pulseapi.creators.models import EntryCreator
from pulseapi.entries.models import Entry
from pulseapi.profiles.models import UserBookmarks
from pulseapi.entries.serializers import (
EntryWithCreatorsBaseSerializer,
EntrySerializerWithV1Creators,
)
from .profiles import UserProfilePublicSerializer
class UserProfileEntriesSerializer(serializers.Serializer):
"""
Serializes entries related to a profile based on the requested
entry types.
Add any combination of the following parameters to the serializer context
to request specific types of entries in the serialized data:
- `created` - List of entries created by the profile
- `published` - List of entries published by the profile
- `favorited` - List of entries favorited/bookmarked by the profile
If none of these parameters are passed in, this serializer falls back to
returning the number of entries (created, published, and favorited) associated
with the profile.
"""
@staticmethod
def get_ordered_queryset(queryset, ordering_param=None, prefix=False):
if not ordering_param:
return queryset
if prefix:
if ordering_param[0] == '-':
ordering_param = '-' + prefix + ordering_param[1:]
else:
ordering_param = prefix + ordering_param
return queryset.order_by(ordering_param)
def to_representation(self, instance):
data = {}
context = self.context
user = context.get('user')
include_created = context.get('created', False)
include_published = context.get('published', False)
include_favorited = context.get('favorited', False)
created_ordering = context.get('created_ordering', False)
published_ordering = context.get('published_ordering', False)
favorited_ordering = context.get('favorited_ordering', False)
EntrySerializerClass = context.get('EntrySerializerClass', EntryWithCreatorsBaseSerializer)
# If none of the filter options are provided, only return the count of
# entries associated with this profile
if not (include_created or include_published or include_favorited):
entry_count = Entry.objects.public().filter(
Q(related_entry_creators__profile=instance) |
Q(published_by=instance.user) |
Q(bookmarked_by__profile=instance)
).distinct().count()
return {
'entry_count': entry_count
}
entry_queryset = Entry.objects.prefetch_related(
'related_entry_creators__profile__related_user',
'bookmarked_by__profile__related_user',
)
if include_created:
entry_creators = UserProfileEntriesSerializer.get_ordered_queryset(
queryset=(
EntryCreator.objects
.prefetch_related(Prefetch('entry', queryset=entry_queryset))
.filter(profile=instance)
.filter(entry__in=Entry.objects.public())
),
ordering_param=created_ordering,
prefix='entry__',
)
data['created'] = [
EntrySerializerClass(
entry_creator.entry,
context={'user': user}
).data
for entry_creator in entry_creators
]
if include_published:
if instance.user:
entries = UserProfileEntriesSerializer.get_ordered_queryset(
queryset=entry_queryset.public().filter(published_by=instance.user),
ordering_param=published_ordering,
)
else:
entries = []
data['published'] = EntrySerializerClass(
entries,
context={'user': user},
many=True
).data
if include_favorited:
user_bookmarks = UserProfileEntriesSerializer.get_ordered_queryset(
queryset=(
UserBookmarks.objects.filter(profile=instance)
.filter(entry__in=Entry.objects.public())
.prefetch_related(Prefetch('entry', queryset=entry_queryset))
),
ordering_param=favorited_ordering,
prefix='entry__',
)
data['favorited'] = [
EntrySerializerClass(bookmark.entry, context={'user': user}).data for bookmark in user_bookmarks
]
return data
class UserProfilePublicWithEntriesSerializer(UserProfilePublicSerializer):
"""
Serializes a user profile for public view and includes all entries
associated with the profile
"""
published_entries = serializers.SerializerMethodField()
def get_published_entries(self, instance):
user = instance.user
return EntrySerializerWithV1Creators(
user.entries.public().with_related().order_by('-id'),
many=True,
context={'user': self.context.get('user')}
).data if user else []
created_entries = serializers.SerializerMethodField()
def get_created_entries(self, instance):
entry_creators = EntryCreator.objects.filter(profile=instance).order_by('-id')
return [EntrySerializerWithV1Creators(x.entry).data for x in entry_creators if x.entry.is_approved()]