summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Hagander2021-08-17 09:52:11 +0000
committerMagnus Hagander2021-08-17 09:52:11 +0000
commit6c44b609f047ab7c0ab6a57331d1133271daef57 (patch)
tree8c902b0deeaa092d83b178021e21532aad7fa6e3
parentfef16dd1d8bf56dafe48b695117fc951a5989677 (diff)
Optimize some db queries
Basically make django generate the joins/prefetches/subqueries instead of firing of hundreds of queries on the db. Probably doesn't actually matter that much given how seldom these queries are run, but still.
-rw-r--r--hamnadmin/hamnadmin/register/management/commands/aggregate_feeds.py5
-rw-r--r--hamnadmin/hamnadmin/register/models.py14
-rw-r--r--hamnadmin/hamnadmin/register/templates/index.html4
-rw-r--r--hamnadmin/hamnadmin/register/views.py27
4 files changed, 25 insertions, 25 deletions
diff --git a/hamnadmin/hamnadmin/register/management/commands/aggregate_feeds.py b/hamnadmin/hamnadmin/register/management/commands/aggregate_feeds.py
index f617fa8..a4f6a85 100644
--- a/hamnadmin/hamnadmin/register/management/commands/aggregate_feeds.py
+++ b/hamnadmin/hamnadmin/register/management/commands/aggregate_feeds.py
@@ -3,7 +3,7 @@ import gevent
from django.core.management.base import BaseCommand
from django.db import transaction
-from django.db.models import Q
+from django.db.models import Q, Exists, OuterRef
from django.conf import settings
from datetime import datetime
@@ -44,6 +44,9 @@ class Command(BaseCommand):
# Fetch all feeds - that are not archived. We do fetch feeds that are not approved,
# to make sure they work.
feeds = Blog.objects.filter(archived=False)
+ feeds = feeds.annotate(
+ has_entries=Exists(Post.objects.filter(feed=OuterRef("pk"), hidden=False)),
+ )
# Fan out the fetching itself
fetchers = [FeedFetcher(f, self.trace) for f in feeds]
diff --git a/hamnadmin/hamnadmin/register/models.py b/hamnadmin/hamnadmin/register/models.py
index 6377a8a..1ce886d 100644
--- a/hamnadmin/hamnadmin/register/models.py
+++ b/hamnadmin/hamnadmin/register/models.py
@@ -50,20 +50,6 @@ class Blog(models.Model):
return self.user.email
@property
- def recent_failures(self):
- return self.aggregatorlog_set.filter(success=False, ts__gt=datetime.now() - timedelta(days=1)).count()
-
- def last_was_error(self):
- if self.lastsuccess:
- return self.aggregatorlog_set.filter(success=False, ts__gt=self.lastsuccess).exists()
- else:
- return self.aggregatorlog_set.filter(success=False).exists()
-
- @property
- def has_entries(self):
- return self.posts.filter(hidden=False).exists()
-
- @property
def latestentry(self):
try:
return self.posts.filter(hidden=False)[0]
diff --git a/hamnadmin/hamnadmin/register/templates/index.html b/hamnadmin/hamnadmin/register/templates/index.html
index 424e620..526b8d6 100644
--- a/hamnadmin/hamnadmin/register/templates/index.html
+++ b/hamnadmin/hamnadmin/register/templates/index.html
@@ -53,8 +53,8 @@ Last successful http fetch dated: {{blog.lastget|date:"Y-m-d H:i:s"}}<br/>
{%endif%}
</div>
<div>
- {% if blog.last_was_error%}<span class="label label-danger">Last attempt failed</span>
- {%else%}<span class="label label-success">Last attempt succeeded</span>{%endif%}
+ {% if blog.last_was_success%}<span class="label label-success">Last attempt succeeded</span>
+ {%else%}<span class="label label-danger">Last attempt failed</span>{%endif%}
{%else%}
<span class="label label-success">Approved and working</span>
{%endif%}{#recent_failures#}
diff --git a/hamnadmin/hamnadmin/register/views.py b/hamnadmin/hamnadmin/register/views.py
index 0a69713..832f4ae 100644
--- a/hamnadmin/hamnadmin/register/views.py
+++ b/hamnadmin/hamnadmin/register/views.py
@@ -3,7 +3,7 @@ from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required, user_passes_test
from django.conf import settings
from django.db import transaction
-from django.db.models import Count, Max
+from django.db.models import Count, Max, Q, Subquery, OuterRef, Exists
from django.contrib import messages
from hamnadmin.register.models import Post, Blog, Team, AggregatorLog, AuditEntry
@@ -18,7 +18,7 @@ from .forms import BlogEditForm, ModerateRejectForm
# Public planet
def planet_home(request):
statdate = datetime.datetime.now() - datetime.timedelta(days=61)
- posts = Post.objects.filter(hidden=False, feed__approved=True).order_by('-dat')[:30]
+ posts = Post.objects.select_related('feed', 'feed__team').filter(hidden=False, feed__approved=True).order_by('-dat')[:30]
topposters = Blog.objects.filter(approved=True, excludestats=False, posts__hidden=False, posts__dat__gt=statdate).annotate(numposts=Count('posts__id')).order_by('-numposts')[:10]
topteams = Team.objects.filter(blog__approved=True, blog__excludestats=False, blog__posts__hidden=False, blog__posts__dat__gt=statdate).annotate(numposts=Count('blog__posts__id')).order_by('-numposts')[:10]
return render(request, 'index.tmpl', {
@@ -49,12 +49,19 @@ def issuperuser(user):
def root(request):
isadmin = request.user.is_superuser and 'admin' in request.GET and request.GET['admin'] == '1'
if isadmin:
- blogs = Blog.objects.all().order_by('archived', 'approved', 'name')
+ blogs = Blog.objects.select_related('user').all()
else:
- blogs = Blog.objects.filter(user=request.user).order_by('archived', 'approved', 'name')
+ blogs = Blog.objects.filter(user=request.user)
+
+ blogs = blogs.annotate(
+ has_entries=Exists(Post.objects.filter(feed=OuterRef("pk"), hidden=False)),
+ recent_failures=Count('aggregatorlog', filter=Q(aggregatorlog__success=False, aggregatorlog__ts__gt=datetime.datetime.now() - datetime.timedelta(days=1))),
+ last_was_success=Subquery(AggregatorLog.objects.filter(feed=OuterRef("pk")).values('success')[:1]),
+ ).order_by('archived', 'approved', 'name')
+
return render(request, 'index.html', {
'blogs': blogs,
- 'teams': Team.objects.filter(manager=request.user).order_by('name'),
+ 'teams': Team.objects.filter(manager=request.user).prefetch_related('blog_set').order_by('name'),
'title': 'All blogs' if isadmin else 'Your blogs',
'isadmin': isadmin,
})
@@ -64,10 +71,14 @@ def root(request):
@transaction.atomic
def edit(request, id=None):
if id:
+ blogqs = Blog.objects.all().annotate(
+ has_entries=Exists(Post.objects.filter(feed=OuterRef("pk"), hidden=False)),
+ recent_failures=Count('aggregatorlog', filter=Q(aggregatorlog__success=False, aggregatorlog__ts__gt=datetime.datetime.now() - datetime.timedelta(days=1))),
+ )
if request.user.is_superuser:
- blog = get_object_or_404(Blog, id=id)
+ blog = get_object_or_404(blogqs, id=id)
else:
- blog = get_object_or_404(Blog, id=id, user=request.user)
+ blog = get_object_or_404(blogqs, id=id, user=request.user)
else:
blog = Blog(user=request.user, name="{0} {1}".format(request.user.first_name, request.user.last_name))
@@ -269,7 +280,7 @@ def blogpost_delete(request, blogid, postid):
@user_passes_test(issuperuser)
def moderate(request):
return render(request, 'moderate.html', {
- 'blogs': Blog.objects.filter(approved=False).annotate(oldest=Max('posts__dat')).order_by('oldest'),
+ 'blogs': Blog.objects.filter(approved=False).select_related('user', 'team').annotate(oldest=Max('posts__dat')).order_by('oldest'),
'title': 'Moderation',
})