Mercurial > public > sg101
changeset 791:0ca691cccf8d
Utilize select_related() for user & user profiles.
This commit also removes the caching of the avatar URL in the
avatar template tag. This is because we are now using select_related,
so we already have the profile & avatar when we get to the tag.
Thus we don't need to waste time querying the cache.
Removed an apparently unused member map template as well.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Fri, 23 May 2014 21:52:41 -0500 |
parents | 6a06080e7ca8 |
children | 7429c98c8ece |
files | bio/templatetags/bio_tags.py comments/templatetags/comment_tags.py forums/views/main.py membermap/views.py sg101/templates/forums/display_post.html sg101/templates/membermap/markdown.html shoutbox/models.py shoutbox/views.py |
diffstat | 8 files changed, 49 insertions(+), 83 deletions(-) [+] |
line wrap: on
line diff
--- a/bio/templatetags/bio_tags.py Fri May 23 15:39:14 2014 -0500 +++ b/bio/templatetags/bio_tags.py Fri May 23 21:52:41 2014 -0500 @@ -30,28 +30,15 @@ @register.inclusion_tag('bio/avatar_tag.html') def avatar(user, profile_link=True, align='bottom'): """ - Returns a dict of attributes for a user's avatar image. + Renders a user's avatar image. - If the user object has an attribute 'user_profile', this is assumed to be - the user's profile that has been pre-fetched. Otherwise, the cache is - consulted to retrieve the avatar info for the user. If there is a cache - miss, only then will we access the profile attribute to retrieve the profile - from the database. + For best results, ensure the user's profile has already been loaded (perhaps + via a select_related()). We no longer cache the avatar url because with + proper use of select_related we will have the user profile already so there + is no need to go spend time checking the cache. """ - # img_info is a tuple that contains info about the avatar: - # (url, width, height) - - if hasattr(user, 'user_profile'): - img_url = get_img_url(user.user_profile) - else: - # try the cache - cache_key = 'avatar_' + user.username - img_url = cache.get(cache_key) - if img_url is None: - profile = user.profile - img_url = get_img_url(profile) - cache.set(cache_key, img_url) + img_url = get_img_url(user.profile) title = user.username style = ''
--- a/comments/templatetags/comment_tags.py Fri May 23 15:39:14 2014 -0500 +++ b/comments/templatetags/comment_tags.py Fri May 23 21:52:41 2014 -0500 @@ -160,7 +160,7 @@ Syntax: {% render_comment_list [object] %} """ - qs = Comment.objects.for_object(object).select_related('user') + qs = Comment.objects.for_object(object).select_related('user', 'user__profile') return { 'comments': qs, 'STATIC_URL': settings.STATIC_URL,
--- a/forums/views/main.py Fri May 23 15:39:14 2014 -0500 +++ b/forums/views/main.py Fri May 23 21:52:41 2014 -0500 @@ -23,12 +23,12 @@ import antispam import antispam.utils -from bio.models import UserProfile, BadgeOwnership +from bio.models import BadgeOwnership from core.paginator import DiggPaginator from core.functions import email_admins, quote_message from forums.models import (Forum, Topic, Post, FlaggedPost, TopicLastVisit, - ForumLastVisit, Attachment) + ForumLastVisit) from forums.forms import (NewTopicForm, NewPostForm, PostForm, MoveTopicForm, SplitTopicForm) from forums.unread import (get_forum_unread_status, get_topic_unread_status, @@ -170,7 +170,9 @@ topic.view_count = F('view_count') + 1 topic.save(force_update=True) - posts = topic.posts.select_related('user') + posts = topic.posts.\ + select_related('user', 'user__profile').\ + prefetch_related('attachments') paginator = create_post_paginator(posts) page_num = get_page_num(request) @@ -180,39 +182,23 @@ raise Http404 get_post_unread_status(topic, page.object_list, request.user) - # Attach user profiles to each post's user to avoid using - # get_user_profile() in the template. - users = set(post.user.id for post in page.object_list) - - profiles = UserProfile.objects.filter(user__id__in=users).select_related() - profile_keys = [profile.id for profile in profiles] - user_profiles = dict((profile.user.id, profile) for profile in profiles) + # Get the BadgeOwnership & Badges for each user who has posted in the + # thread. This is done to save SQL queries in the template. last_post_on_page = None + profile_ids = [] for post in page.object_list: - post.user.user_profile = user_profiles[post.user.id] - post.attach_list = [] last_post_on_page = post + profile_ids.append(post.user.profile.pk) - # Attach badge ownership info to the user profiles to avoid lots - # of database hits in the template: - bos_qs = BadgeOwnership.objects.filter( - profile__id__in=profile_keys).select_related() + bo_qs = BadgeOwnership.objects.filter(profile__in=profile_ids).\ + select_related() bos = collections.defaultdict(list) - for bo in bos_qs: - bos[bo.profile.id].append(bo) + for bo in bo_qs: + bos[bo.profile.pk].append(bo) - for user_id, profile in user_profiles.iteritems(): - profile.badge_ownership = bos[profile.id] - - # Attach any attachments - post_ids = [post.pk for post in page.object_list] - attachments = Attachment.objects.filter(post__in=post_ids).select_related( - 'embed').order_by('order') - - post_dict = dict((post.pk, post) for post in page.object_list) - for item in attachments: - post_dict[item.post.id].attach_list.append(item.embed) + for post in page.object_list: + post.user.profile.badge_ownership = bos[post.user.profile.pk] last_page = page_num == paginator.num_pages @@ -468,8 +454,6 @@ else: form = PostForm(instance=post, topic_name=topic_name) - post.user.user_profile = post.user.profile - return render_to_response('forums/edit_post.html', { 'forum': post.topic.forum, 'topic': post.topic,
--- a/membermap/views.py Fri May 23 15:39:14 2014 -0500 +++ b/membermap/views.py Fri May 23 21:52:41 2014 -0500 @@ -57,9 +57,10 @@ return HttpResponse(s, content_type='application/json') # Compute JSON for the map - entries = MapEntry.objects.all().select_related().order_by('user__username') + entries = MapEntry.objects.select_related('user', 'user__profile').\ + order_by('user__username') users = [] - user_ids = [] + avatar_urls = [] recent = [] for entry in entries.iterator(): users.append(dict(name=entry.user.username, @@ -67,20 +68,17 @@ lon=entry.lon, message=entry.html, )) - user_ids.append(entry.user.id) + avatar = entry.user.profile.avatar + if avatar and avatar.url: + avatar_urls.append(avatar.url) + else: + avatar_urls.append(None) recent.append((entry.date_updated, entry.user.username)) - # Get avatars for all users - profiles = UserProfile.objects.filter(user__in=user_ids).select_related() - avatars = {} - for profile in profiles.iterator(): - if profile.avatar and profile.avatar.url: - avatars[profile.user.username] = profile.avatar.url - # Render the messages that go in the balloons - for user in users: + for user, avatar_url in zip(users, avatar_urls): user['message'] = render_to_string('membermap/balloon.html', - dict(user=user, avatar_url=avatars.get(user['name']))) + dict(user=user, avatar_url=avatar_url)) # Produce the list of recent updates recent.sort(reverse=True)
--- a/sg101/templates/forums/display_post.html Fri May 23 15:39:14 2014 -0500 +++ b/sg101/templates/forums/display_post.html Fri May 23 21:52:41 2014 -0500 @@ -6,27 +6,27 @@ <span class="post-author">{% profile_link post.user.username %}</span><br /> {% avatar post.user %}<br /> Joined: {{ post.user.date_joined|date:"M d, Y" }}<br /> - Posts: {{ post.user.user_profile.forum_post_count }}<br /> - {% if post.user.user_profile.location %} - {{ post.user.user_profile.location }}<br /> + Posts: {{ post.user.profile.forum_post_count }}<br /> + {% if post.user.profile.location %} + {{ post.user.profile.location }}<br /> {% endif %} - {% if post.user.user_profile.country %} - {% flag_icon post.user.user_profile.country 'small' %}<br /> + {% if post.user.profile.country %} + {% flag_icon post.user.profile.country 'small' %}<br /> {% endif %} - {% for bo in post.user.user_profile.badge_ownership %} + {% for bo in post.user.profile.badge_ownership %} <img src="{{ bo.badge.image.url }}" alt="{{ bo.badge_count_str }}" title="{{ bo.badge_count_str }}" /> {% endfor %} {% if user.is_authenticated %} <p> <a href="{% url 'messages-compose_to' post.user.username %}"> <img src="{{ STATIC_URL }}icons/note.png" alt="PM" title="Send Private Message to {{ post.user.username }}" /></a> - {% if not post.user.user_profile.hide_email %}<a href="mailto:{{ post.user.email }}"> + {% if not post.user.profile.hide_email %}<a href="mailto:{{ post.user.email }}"> <img src="{{ STATIC_URL }}icons/email.png" alt="Email" title="Send Email to {{ post.user.username}}" /></a>{% endif %} </p> {% endif %} </td> <td class="forum-post-body"> - <div class="forum-post-info quiet{% if post.user.user_profile.is_stranger %} stranger{% endif %}"> + <div class="forum-post-info quiet{% if post.user.profile.is_stranger %} stranger{% endif %}"> {% if post.unread %}<img src="{{ STATIC_URL }}icons/new.png" alt="New" title="New" />{% endif %} <a href="{{ post.get_absolute_url }}"><img src="{{ STATIC_URL }}icons/link.png" alt="Link" title="Link to this post" /></a> Posted on {% forum_date post.creation_date user %} @@ -34,16 +34,16 @@ </div> <div class="forum-post-body"> {{ post.html|safe }} - {% if post.user.user_profile.signature_html %} - —{{ post.user.user_profile.signature_html|safe }} + {% if post.user.profile.signature_html %} + —{{ post.user.profile.signature_html|safe }} {% endif %} {% if post.has_been_edited %} <p class="small quiet">Last edited: {{ post.update_date|date:"M d, Y H:i:s" }}</p> {% endif %} </div> - {% if post.attach_list %} + {% if post.attachments.all %} <div> - {% for item in post.attach_list %} + {% for item in post.attachments.all %} <div class="forum-attachment">{{ item.html|safe }}</div> {% endfor %} </div> @@ -60,7 +60,7 @@ {% if can_moderate %} <a href="#" class="post-delete" id="dp-{{ post.id }}" title="Delete this post"><img src="{{ STATIC_URL }}icons/cross.png" alt="Delete post" /></a> - {% if post.user != user and post.user.user_profile.is_stranger %} + {% if post.user != user and post.user.profile.is_stranger %} <br /> <span class="quiet">Stranger options:</span> <a href="{% url 'forums-stranger' post.id %}" title="This stranger seems legitimate">
--- a/sg101/templates/membermap/markdown.html Fri May 23 15:39:14 2014 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -{% load markup %} -{% load smiley_tags %} -{% load bio_tags %} -{% avatar user 0 "left" %}{% profile_link user.username %}:<br />{{ msg|safe }}
--- a/shoutbox/models.py Fri May 23 15:39:14 2014 -0500 +++ b/shoutbox/models.py Fri May 23 21:52:41 2014 -0500 @@ -31,7 +31,7 @@ def save(self, *args, **kwargs): if not self.id: self.shout_date = datetime.datetime.now() - self.html = urlize(smilify_html(escape(self.shout)), trim_url_limit=15, + self.html = urlize(smilify_html(escape(self.shout)), trim_url_limit=15, nofollow=True) super(Shout, self).save(*args, **kwargs)
--- a/shoutbox/views.py Fri May 23 15:39:14 2014 -0500 +++ b/shoutbox/views.py Fri May 23 21:52:41 2014 -0500 @@ -54,7 +54,8 @@ def view_history(request): """This view allows one to view the shoutbox history.""" - paginator = DiggPaginator(Shout.objects.all().select_related(), + qs = Shout.objects.select_related('user', 'user__profile') + paginator = DiggPaginator(qs, SHOUTS_PER_PAGE, body=5, tail=3, margin=3, padding=2) page = get_page(request.GET) try: @@ -66,7 +67,7 @@ 'page': the_page, }, context_instance = RequestContext(request)) - + shout_id_re = re.compile(r'shout-(\d+)')