def get_profile(request, username: str = None, category: str = None, status: str = None): if username is None and request.user.is_authenticated(): return redirect('profile', request.user.username, category or 'anime', status or 'seen', permanent=True) is_anonymous = False if username: user = get_object_or_404(User.objects.select_related('profile'), username=username) else: user = request.user is_anonymous = not request.user.is_authenticated() if is_anonymous or username is None: is_shared = True elif user == request.user: is_shared = True else: is_shared = user.profile.is_shared if category is None or status is None: if user.username: return redirect('profile', user.username, category or 'anime', status or 'seen', permanent=True) else: return redirect('my-profile', category or 'anime', status or 'seen', permanent=True) can_see = is_shared or user == request.user seen_works = status == "seen" algo_name = request.GET.get('algo', None) categories = ('anime', 'manga', 'album') # FIXME: We should move natural sorting on the database-side. # This way, we can keep a queryset until the end. # Eventually, we pass it as-is to the paginator, so we have better performance and less memory consumption. # Currently, we load the *entire set* of ratings for a (seen/willsee|wontsee) category of works. ratings, counts = get_profile_ratings(request, category, seen_works, can_see, is_anonymous, user) compare_function = build_profile_compare_function(algo_name, ratings, user) rating_list = natsorted(ratings, key=compare_function) if category == 'recommendation': received_recommendation_list, sent_recommendation_list = get_profile_recommendations( is_anonymous, can_see, user ) else: received_recommendation_list = sent_recommendation_list = [] if can_see and not is_anonymous and not received_recommendation_list: reco_count = Recommendation.objects.filter(target_user=user).count() else: reco_count = len(received_recommendation_list) member_time = (datetime.date.today() - user.date_joined.date() if (can_see and not is_anonymous) else None) user_events = get_profile_events(user) if (can_see and not is_anonymous) else [] paginator = Paginator(rating_list, RATINGS_PER_PAGE) page = request.GET.get('page') try: ratings = paginator.page(page) except PageNotAnInteger: ratings = paginator.page(1) except EmptyPage: ratings = paginator.page(paginator.num_pages) is_me = request.user == user data = { 'meta': { 'debug_vue': settings.DEBUG_VUE_JS, 'mal': { 'is_available': client.is_available and (redis_pool is not None), 'pending_import': None if (not is_me) or is_anonymous else get_current_mal_import(request.user), }, 'config': VANILLA_UI_CONFIG_FOR_RATINGS, 'can_see': can_see, 'username': request.user.username, 'is_shared': is_shared, 'is_me': is_me, 'category': category, 'seen': seen_works, 'is_anonymous': is_anonymous, 'ratings_disabled': request.user != user and not is_anonymous, 'algo_name': algo_name }, 'profile': { 'avatar_url': user.profile.avatar_url if (not is_anonymous and can_see) else None, 'member_days': member_time.days if member_time else None, 'seen_anime_count': counts['seen_anime'], 'seen_manga_count': counts['seen_manga'], 'unseen_anime_count': counts['unseen_anime'], 'unseen_manga_count': counts['unseen_manga'], 'reco_count': reco_count, 'username': user.username }, 'ratings': ratings, 'recommendations': { 'received': received_recommendation_list, 'sent': sent_recommendation_list }, 'events': user_events } return render(request, 'profile.html', data)
def get_profile_works(request, username: str = None, category: str = None, status: str = None): if username is None and request.user.is_authenticated(): return redirect('profile-works', request.user.username, category or 'anime', status or 'seen', permanent=True) user, ctx = get_profile(request, username) if category is None or status is None: if user.username: return redirect('profile-works', user.username, category or 'anime', status or 'seen', permanent=True) else: return redirect('my-profile', category or 'anime', status or 'seen', permanent=True) seen_works = status == "seen" algo_name = request.GET.get('algo', None) # FIXME: We should move natural sorting on the database-side. # This way, we can keep a queryset until the end. # Eventually, we pass it as-is to the paginator, so we have better performance and less memory consumption. # Currently, we load the *entire set* of ratings for a (seen/willsee|wontsee) category of works. ratings, counts = get_profile_ratings(request, category, seen_works, ctx['meta']['can_see'], ctx['meta']['is_anonymous'], user) compare_function = build_profile_compare_function(algo_name, ratings, user) rating_list = natsorted(ratings, key=compare_function) if category == 'recommendation': received_recommendation_list, sent_recommendation_list = get_profile_recommendations( ctx['meta']['is_anonymous'], ctx['meta']['can_see'], user) else: received_recommendation_list = sent_recommendation_list = [] if ctx['meta']['can_see'] and not ctx['meta'][ 'is_anonymous'] and not received_recommendation_list: reco_count = Recommendation.objects.filter(target_user=user).count() else: reco_count = len(received_recommendation_list) paginator = Paginator(rating_list, RATINGS_PER_PAGE) page = request.GET.get('page') try: ratings = paginator.page(page) except PageNotAnInteger: ratings = paginator.page(1) except EmptyPage: ratings = paginator.page(paginator.num_pages) new_ctx = { 'meta': { 'category': category, 'seen': seen_works, 'algo_name': algo_name, 'section': 'works', 'status': status }, 'profile': { 'seen_anime_count': counts['seen_anime'], 'seen_manga_count': counts['seen_manga'], 'unseen_anime_count': counts['unseen_anime'], 'unseen_manga_count': counts['unseen_manga'], 'reco_count': reco_count, 'username': user.username }, 'ratings': ratings, 'recommendations': { 'received': received_recommendation_list, 'sent': sent_recommendation_list }, } return render(request, 'profile_works.html', deep_dict_merge(ctx, new_ctx))