from avatar.models import Avatar from django.db.models import QuerySet from avatar.api.utils import HTMLTagParser from rest_framework.response import Response from rest_framework.decorators import action from avatar.templatetags.avatar_tags import avatar from avatar.api.serializers import AvatarSerializer from rest_framework.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ from rest_framework import viewsets, status, permissions from avatar.api.utils import set_new_primary, assign_width_or_height from avatar.utils import invalidate_cache, get_default_avatar_url, get_primary_avatar class AvatarViewSets(viewsets.ModelViewSet): serializer_class = AvatarSerializer permission_classes = [permissions.IsAuthenticated] queryset = Avatar.objects.select_related('user').order_by('-primary', '-date_uploaded') @property def parse_html_to_json(self): default_avatar = avatar(self.request.user) html_parser = HTMLTagParser() html_parser.feed(default_avatar) return html_parser.output def get_queryset(self): assert self.queryset is not None, ( "'%s' should either include a `queryset` attribute, " "or override the `get_queryset()` method." % self.__class__.__name__ ) queryset = self.queryset if isinstance(queryset, QuerySet): # Ensure queryset is re-evaluated on each request. queryset = queryset.filter(user=self.request.user) return queryset def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) if queryset: page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) data = serializer.data return Response(data) return Response( { "message": "You haven't uploaded an avatar yet. Please upload one now.", "default_avatar": self.parse_html_to_json }) def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) message = _("Successfully uploaded a new avatar.") context_data = { 'message': message, 'data': serializer.data } return Response(context_data, status=status.HTTP_201_CREATED, headers=headers) def destroy(self, request, *args, **kwargs): instance = self.get_object() if instance.primary is True: # Find the next avatar, and set it as the new primary set_new_primary(self.get_queryset(), instance) self.perform_destroy(instance) message = _("Successfully deleted the requested avatars.") return Response(message, status=status.HTTP_204_NO_CONTENT) def update(self, request, *args, **kwargs): partial = kwargs.pop('partial', False) instance = self.get_object() serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True) avatar_image = serializer.validated_data.get('avatar') primary_avatar = serializer.validated_data.get('primary') if not primary_avatar and avatar_image: raise ValidationError('You cant update an avatar image that is not primary') if instance.primary is True: # Find the next avatar, and set it as the new primary set_new_primary(self.get_queryset(), instance) self.perform_update(serializer) invalidate_cache(request.user) message = _("Successfully updated your avatar.") if getattr(instance, '_prefetched_objects_cache', None): # If 'prefetch_related' has been applied to a queryset, we need to # forcibly invalidate the prefetch cache on the instance. instance._prefetched_objects_cache = {} context_data = { 'message': message, 'data': serializer.data } return Response(context_data) @action(['GET'], detail=False, url_path='render_primary', name='Render Primary Avatar') def render_primary(self, request, *args, **kwargs): """ URL Example : 1 - render_primary/ 2 - render_primary/?width=400 or render_primary/?height=400 3 - render_primary/?width=500&height=400 """ context_data = {} avatar_size = assign_width_or_height(request.query_params) width = avatar_size.get('width') height = avatar_size.get('height') primary_avatar = get_primary_avatar(request.user, width=width, height=height) if primary_avatar and primary_avatar.primary: url = primary_avatar.avatar_url(width, height) else: url = get_default_avatar_url() if bool(request.query_params): context_data.update({'message': 'Resize parameters not working for default avatar'}) context_data.update({"image_url": request.build_absolute_uri(url)}) return Response(context_data)