Save HTML for each thought to the DB for performance

This commit is contained in:
Matthias Portzel 2022-09-17 14:00:48 -04:00
parent 650a845611
commit 8fe3852040
8 changed files with 124 additions and 56 deletions

View File

@ -5,6 +5,8 @@ python-decouple~=3.6
jetforce~=0.9.0
django-extensions~=3.2.1
django-debug-toolbar~=3.6.0
progressbar~=4.0.0
git+https://github.com/django-haystack/django-haystack.git
git+https://tildegit.org/matthias/xapian-haystack.git

View File

@ -0,0 +1,11 @@
from progressbar import progressbar
from django.core.management.base import BaseCommand
from thoughts.models import Thought
class Command(BaseCommand):
def handle(self, *args, **options):
for t in progressbar(Thought.objects.all()):
# Saving forces us to re-generate HTML content
t.save()

View File

@ -0,0 +1,24 @@
# Generated by Django 4.0.3 on 2022-09-17 17:54
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('thoughts', '0006_alter_thought_text'),
]
operations = [
migrations.AddField(
model_name='thought',
name='html_content',
field=models.TextField(blank=True),
),
migrations.AlterField(
model_name='thought',
name='posted',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

View File

@ -8,16 +8,21 @@ from django.db import models
from django.utils import timezone
from django.utils.text import normalize_newlines
from django.core.exceptions import ValidationError
from django.template.loader import render_to_string
class Thought(models.Model):
text = models.CharField(max_length=140, blank=True)
extended_text = models.TextField(blank=True)
uuid = models.UUIDField(default=uuid.uuid4, editable=False)
posted = models.DateTimeField(auto_now_add=True)
posted = models.DateTimeField(default=timezone.now)
timezone_offset = models.IntegerField() # The number of minutes behind UTC we were when this was posted
media = models.FileField(upload_to="", blank=True) # A single image, video, or sound clip per post
media_alt = models.TextField(blank=True) # An optional transcription of the Thought's media
html_content = models.TextField(blank=True) # The rendered text for this thought
def save(self):
self.update_html_content(commit=False)
super().save()
def get_media_type(self):
if not self.media:
@ -40,6 +45,17 @@ class Thought(models.Model):
def get_absolute_url(self):
return f"/?show={str(self.uuid)}"
def get_html_content(self, authenticated=False):
return render_to_string("thoughts/thought.html", {"thought": self, "authenticated": authenticated})
def get_html_content_authenticated(self):
return self.get_html_content(authenticated=True)
def update_html_content(self, commit=True):
self.html_content = self.get_html_content()
if commit:
self.save()
@classmethod
def find(cls, identifier):
try:

View File

@ -56,60 +56,18 @@
</nav>
{% endif %}
{% load tz %}
{% for thought in thoughts %}
<div class="thought{% if thought.uuid == highlighted %} highlighted{% endif %}" id="{{ thought.uuid }}">
<div class="main">
<span class="main-text text">{{ thought.text|urlize }}</span>
</div>
{% with file_type=thought.get_media_type %}
{% if file_type or thought.extended_text.strip %}
<div class="extended">
{% if thought.extended_text.strip %}
<span class="extended-text text">{{ thought.extended_text|urlize }}</span>
{% endif %}
{% if file_type == "png" or file_type == "jpeg" or file_type == "jpg" %}
<img src="{{ thought.media.url }}" class="extended-media" alt="{{ thought.media_alt }}">
{% elif file_type == "m4a" or file_type == "mp3" or file_type == "aac" %}
<audio controls src="{{ thought.media.url }}" class="extended-media"></audio>
{% if thought.media_alt %}
<button class="transcript-button">View transcription</button>
<div class="transcript-label">Transcript</div>
<div class="transcript">{{ thought.media_alt|urlize }}</div>
{% endif %}
{% elif file_type == "mov" or file_type == "mp4" %}
<video src="{{ thought.media.url }}" controls class="extended-media"></video>
{% if thought.media_alt %}
<button class="transcript-button">View description</button>
<div class="transcript-label">Description</div>
<div class="transcript">{{ thought.media_alt|urlize }}</div>
{% endif %}
{% endif %}
</div>
{% endif %}
{% endwith %}
<div class="thought-end">
<span class="permalink">
<a class="button" href="/?show={{thought.uuid}}">Link</a>
</span>
{% if thought.uuid == highlighted and authenticated %}
<span class="permalink edit-link">
<a class="button" href="/post?editing={{thought.uuid}}">Edit</a>
</span>
{% endif %}
<span class="timestamp">
{% timezone thought.get_timezone %}
{{ thought.posted|time:"g:i a" }}
{{ thought.posted|date:"M d, Y" }},
UTC{{ thought.get_offset_hours }}
{% endtimezone %}
</span>
</div>
<hr>
</div>
<div class="thought{% if thought.uuid == highlighted %} highlighted{% endif %}" id="{{ thought.uuid }}">
{% if thought.uuid == highlighted %}
{% if authenticated %}
{{ thought.get_html_content_authenticated }}
{% else %}
{{ thought.get_html_content}}
{% endif %}
{% else %}
{{ thought.html_content|safe }}
{% endif %}
</div>
{% endfor %}
<nav class="history-nav bottom" aria-label="History Navigation">

View File

@ -0,0 +1,53 @@
<div class="main">
<span class="main-text text">{{ thought.text|urlize }}</span>
</div>
{% with file_type=thought.get_media_type %}
{% if file_type or thought.extended_text.strip %}
<div class="extended">
{% if thought.extended_text.strip %}
<span class="extended-text text">{{ thought.extended_text|urlize }}</span>
{% endif %}
{% if file_type == "png" or file_type == "jpeg" or file_type == "jpg" %}
<img src="{{ thought.media.url }}" class="extended-media" alt="{{ thought.media_alt }}">
{% elif file_type == "m4a" or file_type == "mp3" or file_type == "aac" %}
<audio controls src="{{ thought.media.url }}" class="extended-media"></audio>
{% if thought.media_alt %}
<button class="transcript-button">View transcription</button>
<div class="transcript-label">Transcript</div>
<div class="transcript">{{ thought.media_alt|urlize }}</div>
{% endif %}
{% elif file_type == "mov" or file_type == "mp4" %}
<video src="{{ thought.media.url }}" controls class="extended-media"></video>
{% if thought.media_alt %}
<button class="transcript-button">View description</button>
<div class="transcript-label">Description</div>
<div class="transcript">{{ thought.media_alt|urlize }}</div>
{% endif %}
{% endif %}
</div>
{% endif %}
{% endwith %}
<div class="thought-end">
<span class="permalink">
<a class="button" href="/?show={{thought.uuid}}">Link</a>
</span>
{% if authenticated %}
<span class="permalink edit-link">
<a class="button" href="/post?editing={{thought.uuid}}">Edit</a>
</span>
{% endif %}
{% load tz %}
<span class="timestamp">
{% timezone thought.get_timezone %}
{{ thought.posted|time:"g:i a" }}
{{ thought.posted|date:"M d, Y" }},
UTC{{ thought.get_offset_hours }}
{% endtimezone %}
</span>
</div>
<hr>

View File

@ -31,6 +31,7 @@ PASSWORD = config("PASSWORD", default="password")
ALLOWED_HOSTS = ["thoughts.learnerpages.com"]
if DEBUG:
ALLOWED_HOSTS = ["*"]
INTERNAL_IPS = ["localhost", "127.0.0.1"]
def split_string(string):
return string.split(",")
@ -44,6 +45,7 @@ INSTALLED_APPS = [
"django.contrib.staticfiles",
"django_extensions",
"debug_toolbar",
"haystack",
@ -66,6 +68,7 @@ HAYSTACK_CONNECTIONS = {
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 1000000
MIDDLEWARE = [
"debug_toolbar.middleware.DebugToolbarMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",

View File

@ -9,5 +9,6 @@ urlpatterns = [
path("about", views.about, name="about"),
path("login", views.login, name="login"),
path("post", views.post, name="post"),
path("search", views.search, name="thoughts_search")
path("search", views.search, name="thoughts_search"),
path('__debug__/', include('debug_toolbar.urls')),
] + (static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) if settings.DEBUG else [])