def posts(request, payload={}, short_id=None): """ Posts endpoint of the example.com public api Request with an id parameter: /public_api/posts/1qkx8 POST JSON in the following format: POST /public_api/posts/ {"ids":["1qkx8","ma6fz"]} """ Metrics.api_comment.record(request) ids = payload.get('ids') if short_id and not ids: try: comment = Comment.details_by_id(long_id(short_id), promoter=PublicAPICommentDetails) (comment,) = CachedCall.multicall([comment]) return comment.to_client() except (ObjectDoesNotExist, util.Base36DecodeException): raise ServiceError("Post not found") elif ids: ids = [long_id(x) for x in set(ids)] calls = [Comment.details_by_id(id, ignore_not_found=True, promoter=PublicAPICommentDetails) for id in ids] comments = CachedCall.multicall(calls, skip_decorator=True) return {'posts': [x.to_client() for x in comments if x]}
def _make_activities(self, activity_ids, earlier_than=None, later_than=None): from apps.activity.models import Activity, LegacyActivity def filter_by_ts(query): if earlier_than is not None: query = query.filter(timestamp__lt=earlier_than) if later_than is not None: query = query.filter(timestamp__gt=later_than) return query activity_ids = [int(id_) for id_ in activity_ids] activities = Activity.objects.filter(id__in=activity_ids).order_by('-timestamp') activities = filter_by_ts(activities) activities = CachedCall.queryset_details(activities) if len(activities) < len(activity_ids): legacy_ids = set(activity_ids) - set(int(activity['id']) for activity in activities) legacy_activities = LegacyActivity.objects.filter(id__in=legacy_ids).order_by('-timestamp') legacy_activities = filter_by_ts(legacy_activities) legacy_activities = CachedCall.queryset_details(legacy_activities) activities.extend(legacy_activities) ret = [] for activity_data in activities: try: ret.append(self._activity_types[activity_data['activity_type']](activity_data)) except KeyError as e: continue return ret
def test_two_cachedcalls_with_same_key_use_same_cache(self): fun = CB(retvalue='bar') cc1 = CachedCall('qix', fun) cc2 = CachedCall('qix', fun) self.assertEqual(cc1(), cc2()) self.assertEqual(1, fun.called)
def test_force_returns_new_value(self): fun = CB(retvalue=1) cc = CachedCall('key', fun) cc() fun.retvalue = 2 self.assertEqual(2, cc.force())
def search_stamps(request, query, start): """ Searches the special "stamps" group for stamps that match the search query. Returns {comments: [list of comment details]} """ qs = query try: start = int(start) except TypeError: raise ServiceError('Invalid "start" parameter.') stamps = models.Category.objects.get(name="stamps") if qs: ids = [ x for x in models.Comment.objects.filter( category=stamps).filter(Q( title__icontains=qs)).values_list('id', flat=True) ] ids = ids[start:start + 32] comments = models.Comment.curated.exclude( reply_content__id=None).in_bulk(ids) details = CachedCall.multicall( [comments[id].details for id in ids if id in comments]) else: comments = models.Comment.curated.filter(category=stamps).exclude( reply_content__id=None).order_by('-id') comments = comments[start:start + 32] details = CachedCall.queryset_details(comments) return {'comments': details}
def search_stamps(request, query, start): """ Searches the special "stamps" group for stamps that match the search query. Returns {comments: [list of comment details]} """ qs = query try: start = int(start) except TypeError: raise ServiceError('Invalid "start" parameter.') stamps = models.Category.objects.get(name="stamps") if qs: ids = [x for x in models.Comment.objects.filter(category=stamps).filter( Q(reply_text__icontains=qs) | Q(title__icontains=qs) ).values_list('id', flat=True)] ids = ids[start:start+32] comments = models.Comment.curated.exclude(reply_content__id=None).in_bulk(ids) details = CachedCall.multicall([comments[id].details for id in ids if id in comments]) else: comments = models.Comment.curated.filter(category=stamps).exclude(reply_content__id=None).order_by('-id') comments = comments[start:start+32] details = CachedCall.queryset_details(comments) return {'comments': details}
def test_queryset_details(self): comments = [create_comment(reply_content=create_content()) for _ in xrange(10)] details1 = CachedCall.multicall([cmt.details for cmt in comments]) queryset = Comment.objects.filter(id__in=[cmt.id for cmt in comments]) details2 = CachedCall.queryset_details(queryset) self.assertEquals(details1, details2)
def test_skip_decorator(self): def decorator(self): raise Exception fun = CB() cc = CachedCall('key', fun, decorator=decorator) self.assertEquals(fun.retvalue, cc(skip_decorator=True)) self.assertEquals(fun.retvalue, cc.force(skip_decorator=True))
def test_force_updates_cached_value(self): fun = CB(retvalue=1) cc = CachedCall('key', fun) cc() fun.retvalue = 2 cc.force() self.assertEqual(2, cc())
def test_many_multicall(self): f1, f2, f3, f4, f5, f6 = [ CachedCall('key_%s' % n, CB(retvalue=n)) for n in [1, 2, 3, 4, 5, 6] ] self.assertEquals([[1], [2, 3], [4, 5, 6]], CachedCall.many_multicall([f1], [f2, f3], [f4, f5, f6]))
def test_multicall_half_cached_returns_results(self): funs = [CB(retvalue=n) for n in [1, 2, 3, 4, 5]] calls = [CachedCall("key_%s" % e, fun) for e, fun in enumerate(funs)] # Uncached self.assertEquals([1, 2, 3], CachedCall.multicall(calls[:3])) # Half cached self.assertEquals([1, 2, 3, 4, 5], CachedCall.multicall(calls)) self.assertEquals([1] * len(funs), [fun.called for fun in funs])
def test_multicall_half_cached_returns_results(self): funs = [CB(retvalue=n) for n in [1,2,3,4,5]] calls = [CachedCall("key_%s" % e, fun) for e,fun in enumerate(funs)] # Uncached self.assertEquals([1,2,3], CachedCall.multicall(calls[:3])) # Half cached self.assertEquals([1,2,3,4,5], CachedCall.multicall(calls)) self.assertEquals([1] * len(funs), [fun.called for fun in funs])
def test_queryset_details(self): comments = [ create_comment(reply_content=create_content()) for _ in xrange(10) ] details1 = CachedCall.multicall([cmt.details for cmt in comments]) queryset = Comment.objects.filter(id__in=[cmt.id for cmt in comments]) details2 = CachedCall.queryset_details(queryset) self.assertEquals(details1, details2)
def test_decorator(self): tocache = {'animals': 2} toadd = {'people': 3} decorator = lambda c: dict(c, **toadd) expected = dict(tocache, **toadd) fun = CB(retvalue=tocache) cc = CachedCall('key', fun, decorator=decorator) self.assertEquals(expected, cc()) # Now test cached. cc = CachedCall('key', fun, decorator=decorator) self.assertEquals(expected, cc()) self.assertEquals(1, fun.called)
def test_inprocess_cached_prevents_multiple_fetches_in_multicall(self): funs = [CB(retvalue=n) for n in [1, 2, 3, 4, 5]] calls = [CachedCall("key_%s" % e, fun) for e, fun in enumerate(funs)] # Uncached self.assertEquals([1, 2, 3], CachedCall.multicall(calls[:3])) # Remove some of the backing stores cache.delete('key_0') cache.delete('key_1') CachedCall.inprocess_cache.delete('key_2') # 1,2 in-process only, 3 in redis only, 4,5 uncached self.assertEquals([1, 2, 3, 4, 5], CachedCall.multicall(calls)) self.assertEquals([1] * len(funs), [fun.called for fun in funs])
def archived_quests(): """ Returns quest details. """ archived_quests = ScheduledQuest.archived(select_quests=True) quests = CachedCall.multicall( [archived.quest.details for archived in archived_quests]) return quests
def user_comments(user, viewer, offset='top', include_ugq=True, include_reactions=True): comments = QuestComment.by_author(user) if not include_ugq: comments = comments.filter(parent_comment__ugq=False) if viewer.id != user.id: comments = comments.exclude(visibility=Visibility.CURATED) if viewer.is_authenticated(): comments = comments.exclude(flags__user=viewer) pagination = Paginator(comments, knobs.COMMENTS_PER_PAGE, offset=offset) comments = pagination.items promoter = None if include_reactions else QuestCommentGalleryDetails comments = CachedCall.queryset_details(comments, promoter=promoter) add_viewer_has_starred_field(comments, viewer=viewer) return comments, pagination
def twitter_followers_on_drawquest(request, twitter_access_token, twitter_access_token_secret): """ Returns one field, `users`, a list of `User` dicts. """ twitter_user = TwitterUser.get_or_create_from_access_token( twitter_access_token, twitter_access_token_secret) twitter_friends = twitter_user.followers_on_drawquest( twitter_access_token, twitter_access_token_secret) twitter_friends = list(twitter_friends.select_related('user')) twitter_friend_uids = dict( (friend.user_id, friend.twitter_uid) for friend in twitter_friends) users = CachedCall.multicall([ User.details_by_id(twitter_friend.user_id) for twitter_friend in twitter_friends if twitter_friend.user_id is not None ]) for user in users: user.twitter_uid = twitter_friend_uids[user.id] if request.user.is_authenticated() and request.user.id != user.id: user.viewer_is_following = request.user.is_following(user.id) return { 'users': users, }
def api_monster_details(request, short_id, payload={}): view_data = CommentViewData(request, short_id) main_comment = view_data.op_comment replies = [Comment.details_by_id(cid) for cid in view_data.reply_ids] has_replies = len(replies) > 0 ( (main_comment,), replies ) = CachedCall.many_multicall( [main_comment], replies, ) treplies = [] made_bottom = False for reply in replies: cur = reply.to_client() if reply.real_author == request.user.username: cur['current_user_authored'] = made_bottom = True treplies.append(cur) ctx = { 'top': main_comment, 'bottoms': treplies, 'current_user_made_bottom': made_bottom, 'current_user_made_top': main_comment.real_author == request.user.username, 'start_content': Content.all_objects.get(id=Content.SMALL_DRAW_FROM_SCRATCH_PK).details(), } return ctx
def from_ids(cls, comment_ids): """ Returns a list of CommentDetails instances. Does not include user pins. """ from canvas.models import Comment details = [ Comment.details_by_id(comment_id) for comment_id in comment_ids ] return CachedCall.many_multicall(details)[0]
def get_suggested_tags(user): number_to_suggest = 3 suggested = set(knobs.SUGGESTED_TOPICS) followed = set(user.redis.followed_tags[:] ) | user.redis.muted_suggested_tags.smembers() unfollowed = suggested - followed # Add preview to tag unfollowed = [{'name': topic} for topic in unfollowed] topic_previews = canvas.models.Content.all_objects.filter( id__in=knobs.SUGGESTED_TOPIC_PREVIEWS.values()) topic_previews = CachedCall.multicall( [preview.details for preview in topic_previews]) preview_mapping = dict([(content['id'], content) for content in topic_previews]) for topic in unfollowed: topic['preview'] = preview_mapping.get( knobs.SUGGESTED_TOPIC_PREVIEWS[topic['name']]) size = len(unfollowed) if size >= number_to_suggest: return sample(unfollowed, number_to_suggest) elif size > 0: return list(unfollowed) else: return []
def test_inprocess_cached_prevents_multiple_fetches_in_multicall(self): funs = [CB(retvalue=n) for n in [1,2,3,4,5]] calls = [CachedCall("key_%s" % e, fun) for e,fun in enumerate(funs)] # Uncached self.assertEquals([1,2,3], CachedCall.multicall(calls[:3])) # Remove some of the backing stores cache.delete('key_0') cache.delete('key_1') CachedCall.inprocess_cache.delete('key_2') # 1,2 in-process only, 3 in redis only, 4,5 uncached self.assertEquals([1,2,3,4,5], CachedCall.multicall(calls)) self.assertEquals([1] * len(funs), [fun.called for fun in funs])
def test_cache_stores_json_correctly(self): fun = CB(retvalue={'foo': ['bar']}) cc = CachedCall('key', fun) self.assertEquals(fun.retvalue, cc()) self.assertEquals(fun.retvalue, cc()) self.assertEquals(1, fun.called)
def brief_replies(self): ids = [x for x in self.replies.values_list('id', flat=True)] calls = [ Comment.details_by_id(id, promoter=BriefPublicAPICommentDetails) for id in ids ] return CachedCall.multicall(calls, skip_decorator=True)
def gallery_comments(quest, offset='top', direction='next', force_comment=None, viewer=None, include_reactions=True): """ Returns comments, pagination. Each comment is itself a dict. """ if force_comment is not None: newer_comments = QuestComment.objects.filter(parent_comment=quest, id__gt=force_comment.id).order_by('id').values_list('id', flat=True) try: offset = list(newer_comments[:knobs.COMMENTS_PER_PAGE / 2])[-1] except IndexError: offset = force_comment.id pagination = Paginator(_exclude_flagged(_all_gallery_comments(quest), viewer), knobs.COMMENTS_PER_PAGE, offset=offset, direction=direction) comments = pagination.items promoter = None if include_reactions else QuestCommentGalleryDetails comments = CachedCall.queryset_details(comments, promoter=promoter) add_viewer_has_starred_field(comments, viewer=viewer) if force_comment is not None and force_comment.id not in [cmt['id'] for cmt in comments]: if force_comment.visibility != Visibility.CURATED: raise Http404() comments.append(force_comment.details()) comments = sorted(comments, key=lambda cmt: -cmt['id']) if viewer is not None and viewer.is_authenticated(): following = viewer.following_ids() for comment in comments: comment.user.viewer_is_following = comment.user.id in following return comments, pagination
def test_second_call_returns_value_without_calling_underlying_function( self): fun = CB() cc = CachedCall('key', fun) cc() self.assertEquals(fun.retvalue, cc()) self.assertEquals(1, fun.called)
def test_inprocess_cache_prevents_multiple_calls_multiple_fetch(self): fun = CB() cc = CachedCall('key', fun) self.assertEqual(fun.retvalue, cc()) cache.delete('key') self.assertEqual(fun.retvalue, cc()) self.assertEqual(1, fun.called)
def from_queryset(cls, comments): bottoms, tops = CachedCall.many_multicall([cmt.details for cmt in comments], [cmt.thread.op.details for cmt in comments]) tiles = [] for bottom, top in zip(bottoms, tops): tile = cls(bottom, top) tiles.append(tile) return tiles
def wrap_comments(comment_list, cls=None): """ `comment_list` must be an iterable containing Comment instances. """ if not cls: cls = CommentDetails return [ cls(d) for d in CachedCall.multicall([cmt.details for cmt in comment_list]) ]
def get_from_comment(cls, comment): candidates = Comment.public.in_bulk_list([comment.id] + comment.top_replies[:10]) candidates = [post for post in candidates if post.reply_content] candidates = sorted(candidates, key=lambda comment: -comment.get_score()[0]) thread = [comment] + candidates[:5] (posts,) = CachedCall.many_multicall([post.details for post in thread]) return cls(*posts)
def starred_comments_gallery(user, offset='top', direction='next'): stars = CommentSticker.objects.filter(user=user).order_by('-timestamp') pagination = Paginator(stars, knobs.COMMENTS_PER_PAGE, offset=offset, direction=direction) comments = CachedCall.multicall([QuestComment.details_by_id(id_) for id_ in pagination.items.values_list('comment_id', flat=True)]) return comments, pagination
def from_queryset(cls, comments): bottoms, tops = CachedCall.many_multicall( [cmt.details for cmt in comments], [cmt.thread.op.details for cmt in comments]) tiles = [] for bottom, top in zip(bottoms, tops): tile = cls(bottom, top) tiles.append(tile) return tiles
def from_queryset_with_viewer_stickers(cls, viewer, comments): bottoms, tops = CachedCall.many_multicall([cmt.details for cmt in comments], [cmt.thread.op.details for cmt in comments]) tiles = [] for bottom, top in zip(bottoms, tops): tile = cls(bottom, top) tile.viewer_sticker = Comment.get_sticker_from_user_for_comment_id(bottom.id, viewer) tiles.append(tile) return tiles
def explore_comment_details(viewer=None): comments = CachedCall.multicall([ QuestComment.details_by_id(id_, promoter=QuestCommentExploreDetails) for id_ in preloaded_explore_comment_ids() ]) add_viewer_has_starred_field(comments, viewer=viewer) return comments
def _profile(request, user, template='profiles/profile.html'): comments = QuestComment.by_author(user) top_comments = models.top_comments(user) if top_comments is None: comments = CachedCall.queryset_details(comments) else: comments, top_comments = CachedCall.many_queryset_details(comments, top_comments) follow_counts = following_models.counts(user) return r2r_jinja(template, { 'target_user': user, 'comments': comments, 'top_comments': top_comments, 'follower_count': follow_counts['followers'], 'following_count': follow_counts['following'], }, request)
def from_queryset_with_viewer_stickers(cls, viewer, comments): bottoms, tops = CachedCall.many_multicall( [cmt.details for cmt in comments], [cmt.thread.op.details for cmt in comments]) tiles = [] for bottom, top in zip(bottoms, tops): tile = cls(bottom, top) tile.viewer_sticker = Comment.get_sticker_from_user_for_comment_id( bottom.id, viewer) tiles.append(tile) return tiles
def staff_pick_stamps(request, page): page = int(page) page_size = 20 b36_ids = knobs.REMIX_IMAGES_STAFF_PICKS[page*page_size:(page+1)*page_size] ids = [util.base36decode(b36_id) for b36_id in b36_ids] details = CachedCall.queryset_details(Comment.objects.in_bulk_list(ids)) return {'comments': details}
def mobile_details_from_queryset(comments): bottoms, tops = CachedCall.many_multicall([cmt.details for cmt in comments], [cmt.thread.op.details for cmt in comments]) tiles = [] for bottom, top in zip(bottoms, tops): tile = { 'top': top, 'bottom': bottom, } tiles.append(tile) return tiles
def _make_activities(self, activity_ids, earlier_than=None, later_than=None): from apps.activity.models import Activity, LegacyActivity def filter_by_ts(query): if earlier_than is not None: query = query.filter(timestamp__lt=earlier_than) if later_than is not None: query = query.filter(timestamp__gt=later_than) return query activity_ids = [int(id_) for id_ in activity_ids] activities = Activity.objects.filter( id__in=activity_ids).order_by('-timestamp') activities = filter_by_ts(activities) activities = CachedCall.queryset_details(activities) if len(activities) < len(activity_ids): legacy_ids = set(activity_ids) - set( int(activity['id']) for activity in activities) legacy_activities = LegacyActivity.objects.filter( id__in=legacy_ids).order_by('-timestamp') legacy_activities = filter_by_ts(legacy_activities) legacy_activities = CachedCall.queryset_details(legacy_activities) activities.extend(legacy_activities) ret = [] for activity_data in activities: try: ret.append(self._activity_types[activity_data['activity_type']] (activity_data)) except KeyError as e: continue return ret
def staff_pick_stamps(request, page): page = int(page) page_size = 20 b36_ids = knobs.REMIX_IMAGES_STAFF_PICKS[page * page_size:(page + 1) * page_size] ids = [util.base36decode(b36_id) for b36_id in b36_ids] details = CachedCall.queryset_details(Comment.objects.in_bulk_list(ids)) return {'comments': details}
def avatar_url(user): """ DO NOT CALL THIS FOR ANONYMOUS POSTS. """ key = 'column' avatar, = CachedCall.multicall([ User.avatar_by_username(user.username), ]) if key in avatar: url = avatar[key]['name'] else: key = user.id if user.is_authenticated() else 0 url = _default_avatar_url(key) return url
def get_from_comment(cls, comment): candidates = Comment.public.in_bulk_list([comment.id] + comment.top_replies[:10]) candidates = [post for post in candidates if post.reply_content] candidates = sorted(candidates, key=lambda comment: -comment.get_score()[0]) thread = [comment] + candidates[:5] (posts, ) = CachedCall.many_multicall( [post.details for post in thread]) return cls(*posts)
def _profile(request, user, template='profiles/profile.html'): comments = QuestComment.by_author(user) top_comments = models.top_comments(user) if top_comments is None: comments = CachedCall.queryset_details(comments) else: comments, top_comments = CachedCall.many_queryset_details( comments, top_comments) follow_counts = following_models.counts(user) return r2r_jinja( template, { 'target_user': user, 'comments': comments, 'top_comments': top_comments, 'follower_count': follow_counts['followers'], 'following_count': follow_counts['following'], }, request)
def user_comments(request, username, page='top'): user = get_object_or_404(User, username=username) comments = QuestComment.by_author(user) if request.user.id != user.id: comments = comments.exclude(visibility=Visibility.CURATED) comments = comments[:knobs.COMMENTS_PER_PAGE] comments = CachedCall.queryset_details(comments) return { 'comments': comments, }
def ugq_by_user(user, offset='top', direction='next', viewer=None): quests = Quest.objects.filter(author=user, ugq=True) if viewer is not None and viewer.is_authenticated(): quests = quests.exclude(flags__user=viewer) quests = quests.order_by('-id') pagination = Paginator(quests, knobs.QUESTS_PER_PAGE, offset=offset, direction=direction) quests = pagination.items quests = CachedCall.queryset_details(quests) return quests, pagination
def user_comments(request, username, since_id=None, before_id=None): user = get_object_or_404(User, username=username) comments = QuestComment.by_author(user) paginator = Paginator(comments, knobs.COMMENTS_PER_PAGE, since_id=since_id, before_id=before_id) comments = paginator.items comments = CachedCall.multicall([cmt.details for cmt in comments]) comments = filter_frozen_comments(comments) return {'comments': comments, 'pagination': paginator}
def _square_avatar(username, image_type, width, height): avatar, = CachedCall.multicall([ User.avatar_by_username(username), ]) if image_type in avatar: url = avatar[image_type]['name'] size = avatar[image_type] else: key = reduce(lambda acc, x: ord(x) + acc, username, 0) url = _default_avatar_url(key) size = {'width':width, 'height':height} return _avatar(url, size, width, height, username)
def from_queryset_with_pins(cls, comments): """ Returns a list of tile details. This will preload this details object with pins, which is more efficient than loading them on demand. """ # Grab the pin data for this user and these comments. details, pins = CachedCall.many_multicall([cmt.details for cmt in comments], [cmt.thread.op.pins for cmt in comments]) tiles = [] for cmt, pins in zip(details, pins): tile = cls(cmt) tile.pins = pins tiles.append(tile) return tiles
def suggested_users(request): user_list = [] users = sample(SUGGESTED_USERS, 5) users = list(User.objects.filter(username__in=users, is_active=True)) for user in users: if user.userinfo.profile_image is not None: avatar_comment = Comment.details_by_id(user.userinfo.profile_image.id)() else: avatar_comment = None is_following = False try: is_following = request.user.is_following(user) except AttributeError: pass user_list.append({ 'user' : user, 'avatar_comment' : avatar_comment, 'is_following' : is_following, 'is_self' : request.user == user, }) topics = sample(SUGGESTED_TOPICS, 5) topics = [{'name': topic} for topic in topics] topic_previews = Content.all_objects.filter(id__in=SUGGESTED_TOPIC_PREVIEWS.values()) topic_previews = CachedCall.multicall([preview.details for preview in topic_previews]) preview_mapping = dict([(content['id'], content) for content in topic_previews]) try: followed_tags = request.user.redis.followed_tags except AttributeError: followed_tags = [] for topic in topics: topic['preview'] = preview_mapping.get(SUGGESTED_TOPIC_PREVIEWS[topic['name']]) topic['is_following'] = topic['name'] in followed_tags ctx = { 'request': request, 'users': user_list, 'topics': topics, } return r2r_jinja('onboarding/suggested_users.html', ctx, request)
def top_gallery_comments(quest, viewer=None, include_reactions=False): comment_ids = top_gallery_comment_ids(quest) comments = QuestComment.objects.filter(id__in=comment_ids).order_by('-star_count') comments = _exclude_flagged(comments, viewer) promoter = None if include_reactions else QuestCommentGalleryDetails comments = CachedCall.queryset_details(comments, promoter=promoter) add_viewer_has_starred_field(comments, viewer=viewer) if viewer is not None and viewer.is_authenticated(): following = viewer.following_ids() for comment in comments: comment.user.viewer_is_following = comment.user.id in following return comments
def twitter_followers_on_drawquest(request, twitter_access_token, twitter_access_token_secret): """ Returns one field, `users`, a list of `User` dicts. """ twitter_user = TwitterUser.get_or_create_from_access_token(twitter_access_token, twitter_access_token_secret) twitter_friends = twitter_user.followers_on_drawquest(twitter_access_token, twitter_access_token_secret) twitter_friends = list(twitter_friends.select_related('user')) twitter_friend_uids = dict((friend.user_id, friend.twitter_uid) for friend in twitter_friends) users = CachedCall.multicall([User.details_by_id(twitter_friend.user_id) for twitter_friend in twitter_friends if twitter_friend.user_id is not None]) for user in users: user.twitter_uid = twitter_friend_uids[user.id] if request.user.is_authenticated() and request.user.id != user.id: user.viewer_is_following = request.user.is_following(user.id) return { 'users': users, }
def facebook_friends_on_drawquest(request, facebook_access_token): """ Returns one field, `users`, a list of `User` dicts. """ fb_user = FacebookUser.get_or_create_from_access_token(facebook_access_token) fb_friends = fb_user.friends_on_drawquest(facebook_access_token).select_related('user') fb_friend_uids = dict((friend.user_id, friend.fb_uid) for friend in fb_friends) users = CachedCall.multicall([User.details_by_id(fb_friend.user_id) for fb_friend in fb_friends if fb_friend.user_id is not None]) for user in users: user.fb_uid = fb_friend_uids[user.id] if request.user.is_authenticated() and request.user.id != user.id: user.viewer_is_following = request.user.is_following(user.id) return { 'users': users, }
def get_suggested_tags(user): number_to_suggest = 3 suggested = set(knobs.SUGGESTED_TOPICS) followed = set(user.redis.followed_tags[:]) | user.redis.muted_suggested_tags.smembers() unfollowed = suggested - followed # Add preview to tag unfollowed = [{"name": topic} for topic in unfollowed] topic_previews = canvas.models.Content.all_objects.filter(id__in=knobs.SUGGESTED_TOPIC_PREVIEWS.values()) topic_previews = CachedCall.multicall([preview.details for preview in topic_previews]) preview_mapping = dict([(content["id"], content) for content in topic_previews]) for topic in unfollowed: topic["preview"] = preview_mapping.get(knobs.SUGGESTED_TOPIC_PREVIEWS[topic["name"]]) size = len(unfollowed) if size >= number_to_suggest: return sample(unfollowed, number_to_suggest) elif size > 0: return list(unfollowed) else: return []
def user_comments(user, viewer, offset="top", include_ugq=True, include_reactions=True): comments = QuestComment.by_author(user) if not include_ugq: comments = comments.filter(parent_comment__ugq=False) if viewer.id != user.id: comments = comments.exclude(visibility=Visibility.CURATED) if viewer.is_authenticated(): comments = comments.exclude(flags__user=viewer) pagination = Paginator(comments, knobs.COMMENTS_PER_PAGE, offset=offset) comments = pagination.items promoter = None if include_reactions else QuestCommentGalleryDetails comments = CachedCall.queryset_details(comments, promoter=promoter) add_viewer_has_starred_field(comments, viewer=viewer) return comments, pagination