Save HTML for each thought to the DB for performance
This commit is contained in:
parent
650a845611
commit
8fe3852040
|
@ -5,6 +5,8 @@ python-decouple~=3.6
|
||||||
jetforce~=0.9.0
|
jetforce~=0.9.0
|
||||||
|
|
||||||
django-extensions~=3.2.1
|
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://github.com/django-haystack/django-haystack.git
|
||||||
git+https://tildegit.org/matthias/xapian-haystack.git
|
git+https://tildegit.org/matthias/xapian-haystack.git
|
||||||
|
|
|
@ -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()
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -8,16 +8,21 @@ from django.db import models
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.text import normalize_newlines
|
from django.utils.text import normalize_newlines
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
|
||||||
class Thought(models.Model):
|
class Thought(models.Model):
|
||||||
text = models.CharField(max_length=140, blank=True)
|
text = models.CharField(max_length=140, blank=True)
|
||||||
extended_text = models.TextField(blank=True)
|
extended_text = models.TextField(blank=True)
|
||||||
uuid = models.UUIDField(default=uuid.uuid4, editable=False)
|
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
|
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 = 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
|
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):
|
def get_media_type(self):
|
||||||
if not self.media:
|
if not self.media:
|
||||||
|
@ -40,6 +45,17 @@ class Thought(models.Model):
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return f"/?show={str(self.uuid)}"
|
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
|
@classmethod
|
||||||
def find(cls, identifier):
|
def find(cls, identifier):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -56,59 +56,17 @@
|
||||||
</nav>
|
</nav>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% load tz %}
|
|
||||||
|
|
||||||
{% for thought in thoughts %}
|
{% for thought in thoughts %}
|
||||||
<div class="thought{% if thought.uuid == highlighted %} highlighted{% endif %}" id="{{ thought.uuid }}">
|
<div class="thought{% if thought.uuid == highlighted %} highlighted{% endif %}" id="{{ thought.uuid }}">
|
||||||
<div class="main">
|
{% if thought.uuid == highlighted %}
|
||||||
<span class="main-text text">{{ thought.text|urlize }}</span>
|
{% if authenticated %}
|
||||||
</div>
|
{{ thought.get_html_content_authenticated }}
|
||||||
|
{% else %}
|
||||||
{% with file_type=thought.get_media_type %}
|
{{ thought.get_html_content}}
|
||||||
{% 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 %}
|
{% endif %}
|
||||||
{% if file_type == "png" or file_type == "jpeg" or file_type == "jpg" %}
|
{% else %}
|
||||||
<img src="{{ thought.media.url }}" class="extended-media" alt="{{ thought.media_alt }}">
|
{{ thought.html_content|safe }}
|
||||||
{% 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 %}
|
{% 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>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
@ -31,6 +31,7 @@ PASSWORD = config("PASSWORD", default="password")
|
||||||
ALLOWED_HOSTS = ["thoughts.learnerpages.com"]
|
ALLOWED_HOSTS = ["thoughts.learnerpages.com"]
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
ALLOWED_HOSTS = ["*"]
|
ALLOWED_HOSTS = ["*"]
|
||||||
|
INTERNAL_IPS = ["localhost", "127.0.0.1"]
|
||||||
|
|
||||||
def split_string(string):
|
def split_string(string):
|
||||||
return string.split(",")
|
return string.split(",")
|
||||||
|
@ -44,6 +45,7 @@ INSTALLED_APPS = [
|
||||||
"django.contrib.staticfiles",
|
"django.contrib.staticfiles",
|
||||||
|
|
||||||
"django_extensions",
|
"django_extensions",
|
||||||
|
"debug_toolbar",
|
||||||
|
|
||||||
"haystack",
|
"haystack",
|
||||||
|
|
||||||
|
@ -66,6 +68,7 @@ HAYSTACK_CONNECTIONS = {
|
||||||
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 1000000
|
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 1000000
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
||||||
"django.middleware.security.SecurityMiddleware",
|
"django.middleware.security.SecurityMiddleware",
|
||||||
"django.middleware.common.CommonMiddleware",
|
"django.middleware.common.CommonMiddleware",
|
||||||
"django.middleware.csrf.CsrfViewMiddleware",
|
"django.middleware.csrf.CsrfViewMiddleware",
|
||||||
|
|
|
@ -9,5 +9,6 @@ urlpatterns = [
|
||||||
path("about", views.about, name="about"),
|
path("about", views.about, name="about"),
|
||||||
path("login", views.login, name="login"),
|
path("login", views.login, name="login"),
|
||||||
path("post", views.post, name="post"),
|
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 [])
|
] + (static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) if settings.DEBUG else [])
|
||||||
|
|
Loading…
Reference in New Issue