aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorBobby <[email protected]>2025-01-02 23:47:41 -0500
committerBobby <[email protected]>2025-01-02 23:47:41 -0500
commita9c4481356e54317584a4f92d7329364f8ad99e3 (patch)
treeafc5991e0c662a9250c7cde64bc08b3b51dc78e8 /apps
parentb6bf53661c750cc11fc4d976a594e3ef19cc7363 (diff)
downloadthatcomputerscientist-a9c4481356e54317584a4f92d7329364f8ad99e3.tar.xz
thatcomputerscientist-a9c4481356e54317584a4f92d7329364f8ad99e3.zip
some optimization stuff
Diffstat (limited to 'apps')
-rwxr-xr-xapps/blog/admin.py11
-rw-r--r--apps/blog/migrations/0022_comment_downvotes_comment_upvotes.py23
-rwxr-xr-xapps/blog/models.py119
-rwxr-xr-xapps/blog/views.py25
4 files changed, 142 insertions, 36 deletions
diff --git a/apps/blog/admin.py b/apps/blog/admin.py
index 157fff51..cd9a25b8 100755
--- a/apps/blog/admin.py
+++ b/apps/blog/admin.py
@@ -191,10 +191,17 @@ class WeblogAdmin(admin.ModelAdmin):
@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
- list_display = ("post", "get_author", "created_at", "edited")
+ list_display = (
+ "post",
+ "get_author",
+ "created_at",
+ "edited",
+ "upvotes",
+ "downvotes",
+ )
list_filter = ("edited", "created_at")
search_fields = ("body", "user__username", "anonymous_user__name")
- readonly_fields = ("created_at", "edited", "edited_at")
+ readonly_fields = ("created_at", "edited_at")
def get_author(self, obj):
return obj.user.username if obj.user else obj.anonymous_user.name
diff --git a/apps/blog/migrations/0022_comment_downvotes_comment_upvotes.py b/apps/blog/migrations/0022_comment_downvotes_comment_upvotes.py
new file mode 100644
index 00000000..0281c686
--- /dev/null
+++ b/apps/blog/migrations/0022_comment_downvotes_comment_upvotes.py
@@ -0,0 +1,23 @@
+# Generated by Django 5.1.4 on 2025-01-03 01:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('blog', '0021_categorytranslation_tagtranslation'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='comment',
+ name='downvotes',
+ field=models.IntegerField(default=0),
+ ),
+ migrations.AddField(
+ model_name='comment',
+ name='upvotes',
+ field=models.IntegerField(default=0),
+ ),
+ ]
diff --git a/apps/blog/models.py b/apps/blog/models.py
index 9fa7eb30..bdfb6921 100755
--- a/apps/blog/models.py
+++ b/apps/blog/models.py
@@ -64,18 +64,62 @@ class PostTranslation(Translation):
class TranslatableMixin:
+ @classmethod
+ def translate_queryset(cls, queryset, language_code="en"):
+ processed_objects = set()
+ return [obj.translate(language_code, processed_objects) for obj in queryset]
+
+ def translate(self, language_code="en", processed_objects=None):
+ if processed_objects is None:
+ processed_objects = set()
+
+ instance_id = f"{self.__class__.__name__}_{self.pk}"
+ if instance_id in processed_objects:
+ return self
+
+ processed_objects.add(instance_id)
+ translation = self.get_translation(language_code)
+
+ if translation:
+ translated_fields = [
+ field.name
+ for field in translation._meta.get_fields()
+ if not field.is_relation
+ and field.name not in ["id", "language", "created_at", "updated_at"]
+ ]
+
+ for field_name in translated_fields:
+ translated_value = getattr(translation, field_name, None)
+ if translated_value is not None:
+ setattr(self, field_name, translated_value)
+
+ self._translate_relations(language_code, processed_objects)
+ return self
+
+ def _translate_relations(self, language_code, processed_objects):
+ for field in self._meta.get_fields():
+ if not hasattr(field, "related_model") or not hasattr(
+ field.related_model, "translate"
+ ):
+ continue
+
+ if field.one_to_many or field.many_to_many:
+ related_manager = getattr(self, field.name, None)
+ if related_manager and hasattr(related_manager, "all"):
+ for obj in related_manager.all():
+ obj.translate(language_code, processed_objects)
+
+ elif field.many_to_one or field.one_to_one:
+ related_obj = getattr(self, field.name, None)
+ if related_obj and hasattr(related_obj, "translate"):
+ related_obj.translate(language_code, processed_objects)
+
def get_translation(self, language_code):
try:
return self.translations.get(language=language_code)
except self.translations.model.DoesNotExist:
return None
- def translate(self, field_name, language_code="en"):
- translation = self.get_translation(language_code)
- if translation and hasattr(translation, field_name):
- return getattr(translation, field_name)
- return getattr(self, field_name)
-
class Weblog(models.Model):
name = models.CharField(max_length=100)
@@ -94,7 +138,7 @@ class Weblog(models.Model):
return self.name
-class Category(models.Model):
+class Category(TranslatableMixin, models.Model):
weblog = models.ForeignKey(Weblog, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
name_ja = models.CharField(
@@ -120,7 +164,7 @@ class Category(models.Model):
return self.translate("name", language_code)
-class Tag(models.Model):
+class Tag(TranslatableMixin, models.Model):
weblog = models.ForeignKey(Weblog, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
name_ja = models.CharField(
@@ -145,7 +189,7 @@ class Tag(models.Model):
return self.translate("name", language_code)
-class Post(models.Model):
+class Post(TranslatableMixin, models.Model):
weblog = models.ForeignKey(Weblog, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
title_ja = models.CharField(
@@ -176,15 +220,52 @@ class Post(models.Model):
def __str__(self):
return f"{self.weblog.name} - {self.title}"
- def get_excerpt(self, language_code="en", length=1000):
- content = self.get_body(language_code)
- soup = BeautifulSoup(content, "html.parser")
- excerpt = ""
- for paragraph in soup.find_all("p"):
- excerpt += f"<p>{paragraph.text}</p>"
- if len(excerpt) >= length:
- break
- return excerpt
+ def get_excerpt(self, length=1000):
+ if not hasattr(self, "_excerpt"):
+ soup = BeautifulSoup(self.body, "html.parser")
+ excerpt = ""
+ for paragraph in soup.find_all("p"):
+ paragraph = "<p>" + str(paragraph) + "</p>"
+ excerpt += str(paragraph)
+
+ if len(excerpt) >= length:
+ break
+ self._excerpt = excerpt
+ return self._excerpt
+
+ @property
+ def excerpt(self):
+ return self.get_excerpt()
+
+ def get_processed_body(self):
+ if not hasattr(self, "_processed_body"):
+ soup = BeautifulSoup(self.body, "html.parser")
+ first_p = soup.find("p")
+
+ self._first_paragraph = str(first_p) if first_p else ""
+ if first_p:
+ first_p.decompose()
+
+ self._processed_body = str(soup)
+
+ return self._processed_body
+
+ @property
+ def processed_body(self):
+ return self.get_processed_body()
+
+ @property
+ def first_paragraph(self):
+ if not hasattr(self, "_first_paragraph"):
+ self.get_processed_body()
+ return self._first_paragraph
+
+ def translate(self, language_code="en", processed_objects=None):
+ instance = super().translate(language_code, processed_objects)
+ if hasattr(instance, "_processed_body"):
+ delattr(instance, "_processed_body")
+ delattr(instance, "_first_paragraph")
+ return instance
class AnonymousCommentUser(models.Model):
@@ -218,6 +299,8 @@ class Comment(models.Model):
parent = models.ForeignKey(
"self", on_delete=models.CASCADE, null=True, blank=True, related_name="replies"
)
+ upvotes = models.IntegerField(default=0)
+ downvotes = models.IntegerField(default=0)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
edited = models.BooleanField(default=False)
diff --git a/apps/blog/views.py b/apps/blog/views.py
index f590ee2b..d2f6c647 100755
--- a/apps/blog/views.py
+++ b/apps/blog/views.py
@@ -7,23 +7,16 @@ from bs4 import BeautifulSoup
def single_post(request, slug):
try:
- post = Post.objects.get(slug=slug)
-
lang_code = request.LANGUAGE_CODE
- if lang_code == "ja":
- post.body = highlight_code(post.body_ja)
- else:
- post.body = highlight_code(post.body)
-
- soup = BeautifulSoup(post.body, "html.parser")
- first_paragraph = soup.find("p")
- if first_paragraph is not None:
- first_paragraph = str(first_paragraph)
- soup.find("p").decompose()
-
- post.first_paragraph = first_paragraph
- post.body = str(soup)
-
+ post = (
+ Post.objects.select_related("category")
+ .prefetch_related(
+ "tags", "translations", "category__translations", "tags__translations"
+ )
+ .get(slug=slug)
+ .translate(lang_code)
+ )
+ post.body = highlight_code(post.processed_body)
return render(request, "shared/blog/single_weblog.html", {"post": post})
except Post.DoesNotExist:
return HttpResponseNotFound()