from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.db.models import Count, Q, F from tastypie import fields from tastypie.authentication import Authentication from tastypie.authorization import Authorization from django.conf.urls import url from tastypie.constants import ALL, ALL_WITH_RELATIONS from tastypie.http import HttpGone, HttpMultipleChoices from tastypie.utils import trailing_slash from tastypie_msgpack import Serializer from dss import settings from spa.api.v1.BaseResource import BaseResource from spa.api.v1.PlaylistResource import PlaylistResource from spa.models.basemodel import BaseModel from spa.models.userprofile import UserProfile from spa.models.mix import Mix from core.tasks import update_geo_info_task class UserResource(BaseResource): following = fields.ToManyField(to='self', attribute='following', related_name='following', null=True) followers = fields.ToManyField(to='self', attribute='followers', related_name='followers', null=True) favourites = fields.ToManyField('spa.api.v1.MixResource.MixResource', 'favourites', null=True) playlists = fields.ToManyField('spa.api.v1.PlaylistResource.PlaylistResource', 'playlists', related_name='user', null=True, full=True) class Meta: queryset = UserProfile.objects.all().annotate(mix_count=Count('mixes')).order_by('-mix_count') serializer = Serializer() resource_name = 'user' if not settings.DEBUG: excludes = ['is_active', 'is_staff', 'is_superuser', 'password'] ordering = ['mix_count'] filtering = { 'slug': ALL, 'display_name': ALL, 'following': ALL_WITH_RELATIONS, 'followers': ALL_WITH_RELATIONS, 'favourites': ALL_WITH_RELATIONS, 'playlists': ALL_WITH_RELATIONS, } authorization = Authorization() authentication = Authentication() def prepend_urls(self): return [ url(r"^(?P%s)/(?P\d+)%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), url(r"^(?P%s)/(?P[\w\d_.-]+)%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), ] def apply_filters(self, request, applicable_filters): semi_filtered = super(UserResource, self).apply_filters(request, applicable_filters) q = request.GET.get('q', None) if q is not None: semi_filtered = semi_filtered.filter( Q(user__first_name__icontains=q) | Q(user__last_name__icontains=q) | Q(display_name__icontains=q) ) return semi_filtered def obj_create(self, bundle, **kwargs): return super(UserResource, self).obj_create(bundle, **kwargs) def obj_update(self, bundle, skip_errors=False, **kwargs): return super(UserResource, self).obj_update(bundle, skip_errors, **kwargs) def _create_playlist(self, request): pass def get_playlists(self, request, **kwargs): if request.method == 'POST': return self._create_playlist(request) try: basic_bundle = self.build_bundle(request=request) obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return HttpGone() child_resource = PlaylistResource() return child_resource.get_list(request, mix=obj) def dehydrate_description(self, bundle): return bundle.obj.get_profile_description() def dehydrate(self, bundle): del bundle.data['activity_sharing_networks'] bundle.data['display_name'] = bundle.obj.get_nice_name() bundle.data['avatar_image'] = bundle.obj.get_avatar_image() bundle = BaseResource.dehydrate_bitfield( bundle=bundle, field_name='email_notifications', object_field=bundle.obj.email_notifications, choices=UserProfile.NOTIFICATION_CHOICES, ) bundle = BaseResource.dehydrate_bitfield( bundle=bundle, field_name='activity_sharing_facebook', object_field=bundle.obj.activity_sharing_facebook, choices=UserProfile.NOTIFICATION_CHOICES, ) bundle = BaseResource.dehydrate_bitfield( bundle=bundle, field_name='activity_sharing_twitter', object_field=bundle.obj.activity_sharing_twitter, choices=UserProfile.NOTIFICATION_CHOICES, ) if bundle.obj.user.id == bundle.request.user.id: bundle.data['email'] = bundle.obj.email bundle.data['first_name'] = bundle.obj.first_name bundle.data['last_name'] = bundle.obj.last_name bundle.data['like_count'] = Mix.objects.filter(likes__user=bundle.obj).count() bundle.data['favourite_count'] = Mix.objects.filter(favourites__user=bundle.obj).count() # bundle.data['follower_count'] = bundle.obj.followers.count() bundle.data['following_count'] = bundle.obj.following.count() bundle.data['is_following'] = bundle.obj.is_follower(bundle.request.user) bundle.data['url'] = bundle.obj.get_profile_url() bundle.data['date_joined'] = bundle.obj.user.date_joined bundle.data['last_login'] = bundle.obj.user.last_login bundle.data['mix_count'] = bundle.obj.mix_count bundle.data['thumbnail'] = bundle.obj.get_small_profile_image() return bundle def hydrate(self, bundle): bundle = BaseResource.hydrate_bitfield( bundle=bundle, field_name='email_notifications', object_field=UserProfile.email_notifications, choices=UserProfile.NOTIFICATION_CHOICES, ) bundle = BaseResource.hydrate_bitfield( bundle=bundle, field_name='activity_sharing_facebook', object_field=UserProfile.activity_sharing_facebook, choices=UserProfile.NOTIFICATION_CHOICES, ) bundle = BaseResource.hydrate_bitfield( bundle=bundle, field_name='activity_sharing_twitter', object_field=UserProfile.activity_sharing_twitter, choices=UserProfile.NOTIFICATION_CHOICES, ) return bundle def get_followers(self, request, **kwargs): try: basic_bundle = self.build_bundle(request=request) obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs)) except ObjectDoesNotExist: return HttpGone() except MultipleObjectsReturned: return HttpMultipleChoices("More than one resource is found at this URI.") child_resource = UserResource() return child_resource.get_list(request, followers__in=obj)