from django.db.models import Count from rest_framework import serializers from core.utils.html import strip_tags from dss import settings from spa import models from spa.models import Activity, Message from spa.models.activity import ActivityDownload, ActivityPlay from spa.models.blog import Blog from spa.models.genre import Genre from spa.models.notification import Notification from spa.models.show import Show from spa.models.userprofile import UserProfile from spa.models.mix import Mix, MixUpdateException from spa.models.comment import Comment class InlineMixSerializer(serializers.ModelSerializer): class Meta: model = Mix fields = ( 'title', 'slug', 'title', 'description', 'mix_image', ) mix_image = serializers.ReadOnlyField(source='get_image_url') class InlineUserProfileSerializer(serializers.ModelSerializer): is_following = serializers.SerializerMethodField() profile_image_small = serializers.SerializerMethodField() profile_image_medium = serializers.SerializerMethodField() profile_image_header = serializers.SerializerMethodField() class Meta: model = UserProfile fields = ( 'slug', 'first_name', 'last_name', 'display_name', 'is_following', 'profile_image_small', 'profile_image_medium', 'profile_image_header', ) first_name = serializers.ReadOnlyField(source='get_first_name') last_name = serializers.ReadOnlyField(source='get_last_name') display_name = serializers.ReadOnlyField(source='get_nice_name') def get_avatar_image(self, obj): return obj.get_sized_avatar_image(64, 64) def get_avatar_image_tiny(self, obj): return obj.get_sized_avatar_image(64, 64) def to_representation(self, instance): if instance.user.is_anonymous(): return { 'avatar_image': settings.DEFAULT_USER_IMAGE, 'display_name': settings.DEFAULT_USER_NAME, 'slug': '' } return super(serializers.ModelSerializer, self).to_representation(instance) def get_is_following(self, obj): return obj.is_follower(self.context['request'].user) def get_profile_image_small(self, obj): return obj.get_sized_avatar_image(64, 64) def get_profile_image_medium(self, obj): return obj.get_sized_avatar_image(170, 170) def get_profile_image_header(self, obj): return obj.get_sized_avatar_image(1200, 150) class LikeSerializer(serializers.ModelSerializer): class Meta: model = UserProfile fields = ( 'display_name', 'slug', ) display_name = serializers.ReadOnlyField(source='get_nice_name') class GenreSerializer(serializers.ModelSerializer): class Meta: model = Genre fields = ( 'slug', 'description' ) class InlineActivitySerializer(serializers.ModelSerializer): user = serializers.SerializerMethodField() def get_user(self, obj): try: if obj.user is not None: return obj.user.get_nice_name() except: pass return settings.DEFAULT_USER_NAME class InlineActivityPlaySerializer(InlineActivitySerializer): class Meta: model = ActivityPlay fields = ( 'user', 'date' ) class InlineActivityDownloadSerializer(InlineActivitySerializer): class Meta: model = ActivityDownload fields = ( 'user', 'date' ) class MixSerializer(serializers.ModelSerializer): class Meta: model = models.Mix fields = [ 'id', 'slug', 'uid', 'title', 'description', 'user', 'duration', 'waveform_url', 'waveform_progress_url', 'mix_image', 'is_featured', 'is_downloadable', 'is_private', 'can_edit', 'genres', 'likes', 'favourites', 'plays', 'downloads', 'is_liked', ] slug = serializers.ReadOnlyField(required=False) user = InlineUserProfileSerializer(read_only=True) waveform_url = serializers.ReadOnlyField(source='get_waveform_url') waveform_progress_url = serializers.ReadOnlyField(source='get_waveform_progress_url') mix_image = serializers.ReadOnlyField(source='get_image_url') can_edit = serializers.SerializerMethodField() genres = GenreSerializer(many=True, required=False, read_only=True) likes = LikeSerializer(many=True, required=False, read_only=True) # slug_field='slug', many=True, read_only=True) favourites = serializers.SlugRelatedField(slug_field='slug', many=True, read_only=True) plays = InlineActivityPlaySerializer(many=True, read_only=True, source='activity_plays') downloads = InlineActivityDownloadSerializer(read_only=True, source='activity_downloads') is_liked = serializers.SerializerMethodField(read_only=True) def update(self, instance, validated_data): # all nested representations need to be serialized separately here try: # get any likes that aren't in passed bundle likes = self.initial_data['likes'] unliked = instance.likes.exclude(user__userprofile__slug__in=[l['slug'] for l in likes]) for ul in unliked: # check that the user removing the like is an instance of the current user # for now, only the current user can like stuff if ul == self.context['request'].user.userprofile: instance.update_liked(ul, False) for like in likes: # check that the user adding the like is an instance of the current user # for now, only the current user can like stuff try: user = UserProfile.objects.get(slug=like['slug']) if user is not None and user == self.context['request'].user.userprofile: instance.update_liked(user, True) except UserProfile.DoesNotExist: pass # get any likes that aren't in passed bundle if 'downloads' in validated_data: plays = validated_data['downloads'] or [] for play in plays: instance.add_play(play) validated_data.pop('downloads', None) if 'genres' in validated_data: genres = validated_data['genres'] or [] for genre in genres: instance.add_genre(genre) validated_data.pop('genres', None) return super(MixSerializer, self).update(instance, validated_data) except MixUpdateException as ex: raise ex def is_valid(self, raise_exception=False): return super(MixSerializer, self).is_valid(raise_exception) def get_avatar_image(self, obj): return obj.user.get_sized_avatar_image(64, 64) def get_can_edit(self, obj): user = self.context['request'].user if user.is_authenticated(): return user.is_staff or obj.user.id == user.userprofile.id return False def get_is_favourited(self, obj): user = self.context['request'].user return obj.is_favourited(user) if user.is_authenticated() else False def get_validation_exclusions(self, instance=None): exclusions = super(MixSerializer, self).get_validation_exclusions() return exclusions + ['genres', 'comments', 'slug', 'user'] def get_is_liked(self, obj): user = self.context['request'].user return obj.is_liked(user) if user.is_authenticated() else False class UserProfileSerializer(serializers.ModelSerializer): roles = serializers.SerializerMethodField() likes = serializers.SlugRelatedField(slug_field='slug', many=True, read_only=True) favourites = serializers.SlugRelatedField(slug_field='slug', many=True, read_only=True) following = InlineUserProfileSerializer(many=True, read_only=True) followers = InlineUserProfileSerializer(many=True, read_only=True) mix_count = serializers.SerializerMethodField() isme = serializers.SerializerMethodField() email = serializers.SerializerMethodField() date_joined = serializers.SerializerMethodField() last_login = serializers.SerializerMethodField() title = serializers.SerializerMethodField() profile_image_small = serializers.SerializerMethodField() profile_image_medium = serializers.SerializerMethodField() profile_image_header = serializers.SerializerMethodField() top_tags = serializers.SerializerMethodField() class Meta: model = UserProfile lookup_field = 'slug' fields = ( 'id', 'roles', 'date_joined', 'last_login', 'first_name', 'last_name', 'display_name', 'description', 'title', 'profile_image_small', 'profile_image_medium', 'profile_image_header', 'slug', 'likes', 'mix_count', 'isme', 'email', 'favourites', 'following', 'followers', 'top_tags', 'activity_sharing_facebook', 'activity_sharing_twitter', 'email_notifications', ) def update(self, instance, validated_data): following = self.initial_data['following'] unfollowed = instance.following.exclude(user__userprofile__slug__in=[l['slug'] for l in following]) for uf in unfollowed: # check that the user removing the follow is an instance of the current user # for now, only the current user can follow/unfollow stuff instance.remove_following(uf) for follow in following: try: user = UserProfile.objects.get(slug=follow['slug']) if user not in instance.following.all(): instance.add_following(user) except UserProfile.DoesNotExist: pass return super(UserProfileSerializer, self).update(instance, validated_data) def get_title(self, obj): try: if obj.description: return strip_tags(obj.description[:128] + (obj.description[128:] and '..')) else: return settings.DEFAULT_USER_TITLE except: return settings.DEFAULT_USER_TITLE def get_roles(self, obj): try: return obj.get_roles() except Exception as ex: print("Error getting roles: " + ex) return [] def get_isme(self, obj): return self.context['request'].user.pk == obj.user_id def get_email(self, obj): if self.context['request'].user.pk == obj.user_id: return obj.user.email else: return "" def get_mix_count(self, obj): return obj.mix_count def get_date_joined(self, obj): return obj.user.date_joined def get_last_login(self, obj): return obj.user.last_login def get_top_tags(self, obj): return list( Genre.objects.filter(mix__user__slug='fergalmoran'). annotate(total=Count('mix')). order_by('-total'). values('total', 'description', 'slug')[0:3]) def get_profile_image_small(self, obj): return obj.get_sized_avatar_image(64, 64) def get_profile_image_medium(self, obj): return obj.get_sized_avatar_image(170, 170) def get_profile_image_header(self, obj): return obj.get_sized_avatar_image(1200, 150) class CommentSerializer(serializers.HyperlinkedModelSerializer): user = InlineUserProfileSerializer(source='get_comment_user', read_only=True) avatar_image = serializers.SerializerMethodField() mix = serializers.PrimaryKeyRelatedField(read_only=True) display_name = serializers.SerializerMethodField() slug = serializers.SerializerMethodField() can_edit = serializers.SerializerMethodField() class Meta: model = Comment fields = ( 'id', 'user', 'comment', 'time_index', 'date_created', 'user', 'avatar_image', 'mix', 'display_name', 'slug', 'can_edit' ) def get_comment_user(self, obj): return UserProfile.get_user(self.user) def get_display_name(self, obj): if obj.user is not None: return obj.user.userprofile.get_nice_name() else: return settings.DEFAULT_USER_NAME def get_slug(self, obj): if obj.user is not None: return obj.user.userprofile.slug else: return "" def get_avatar_image(self, obj): if obj.user is not None: return obj.user.userprofile.get_sized_avatar_image(48, 48) else: return settings.DEFAULT_USER_IMAGE def get_can_edit(self, obj): user = self.context['request'].user if user is not None and obj.user is not None and user.is_authenticated(): return user.is_staff or obj.user.id == user.userprofile.id return False class HitlistSerializer(serializers.ModelSerializer): display_name = serializers.SerializerMethodField(method_name='get_display_name') avatar_image = serializers.SerializerMethodField(method_name='get_avatar_image') class Meta: model = UserProfile fields = ( 'display_name', 'description', 'slug', 'avatar_image' ) def get_display_name(self, obj): return obj.get_nice_name() def get_avatar_image(self, obj): return obj.get_sized_avatar_image(170, 170) class ActivitySerializer(serializers.HyperlinkedModelSerializer): from_user = InlineUserProfileSerializer(source='get_user') to_user = InlineUserProfileSerializer(source='get_target_user') verb = serializers.CharField(source='get_verb_past') object_type = serializers.CharField(source='get_object_type') object_name = serializers.CharField(source='get_object_name') object_slug = serializers.CharField(source='get_object_slug') class Meta: model = Activity fields = ( 'id', 'date', 'from_user', 'to_user', 'verb', 'object_type', 'object_name', 'object_slug', ) class NotificationSerializer(serializers.HyperlinkedModelSerializer): from_user = InlineUserProfileSerializer(source='get_from_user', read_only=True) notification_url = serializers.ReadOnlyField() verb = serializers.ReadOnlyField() target = serializers.ReadOnlyField() date = serializers.ReadOnlyField() class Meta: model = Notification fields = ( 'id', 'notification_url', 'from_user', 'verb', 'target', 'target_desc', 'type', 'date', 'accepted_date', ) def get_display_name(self, obj): return settings.DEFAULT_USER_NAME if obj.from_user is None else obj.from_user.get_nice_name() def get_avatar_image(self, obj): return settings.DEFAULT_USER_IMAGE if obj.from_user is None else obj.from_user.get_sized_avatar_image(170, 170) class MessageSerializer(serializers.ModelSerializer): from_user = InlineUserProfileSerializer(read_only=True) to_user = InlineUserProfileSerializer(read_only=True) class Meta: model = Message fields = ( 'id', 'from_user', 'to_user', 'sent_at', 'read_at', 'body', ) class ShowSerializer(serializers.ModelSerializer): performer = InlineUserProfileSerializer(read_only=True) user = InlineUserProfileSerializer(read_only=True) class Meta: model = Show """ fields = ( 'id', 'start_date', 'end_date', 'user', 'performer', 'recurrence', 'description' ) """ class BlogSerializer(serializers.ModelSerializer): slug = serializers.ReadOnlyField(required=False) user = InlineUserProfileSerializer(read_only=True) class Meta: model = Blog