diff options
| author | Bobby <[email protected]> | 2025-01-02 00:39:47 -0500 |
|---|---|---|
| committer | Bobby <[email protected]> | 2025-01-02 00:39:47 -0500 |
| commit | b6bf53661c750cc11fc4d976a594e3ef19cc7363 (patch) | |
| tree | ea167939b2ef72ca8f338339edf81a9c0fa1b15d /apps | |
| parent | f55a21547d3838681276d518eded9d6ffcb57903 (diff) | |
| download | thatcomputerscientist-b6bf53661c750cc11fc4d976a594e3ef19cc7363.tar.xz thatcomputerscientist-b6bf53661c750cc11fc4d976a594e3ef19cc7363.zip | |
single weblog template and multi user weblog preparations
Diffstat (limited to 'apps')
| -rwxr-xr-x | apps/blog/admin.py | 213 | ||||
| -rw-r--r-- | apps/blog/migrations/0019_posttranslation_weblog_alter_category_options_and_more.py | 153 | ||||
| -rw-r--r-- | apps/blog/migrations/0020_alter_category_weblog_alter_post_weblog_and_more.py | 32 | ||||
| -rw-r--r-- | apps/blog/migrations/0021_categorytranslation_tagtranslation.py | 44 | ||||
| -rwxr-xr-x | apps/blog/models.py | 220 | ||||
| -rwxr-xr-x | apps/blog/views.py | 20 | ||||
| -rwxr-xr-x | apps/core/views.py | 3 | ||||
| -rwxr-xr-x | apps/journals/views.py | 6 |
8 files changed, 630 insertions, 61 deletions
diff --git a/apps/blog/admin.py b/apps/blog/admin.py index dd35e8cb..157fff51 100755 --- a/apps/blog/admin.py +++ b/apps/blog/admin.py @@ -1,10 +1,209 @@ from django.contrib import admin +from django import forms +from .models import ( + AnonymousCommentUser, + Category, + Comment, + Post, + Tag, + Weblog, + PostTranslation, + CategoryTranslation, + TagTranslation, +) -# Register your models here. -from .models import AnonymousCommentUser, Category, Comment, Post, Tag -admin.site.register(Post) -admin.site.register(Comment) -admin.site.register(Category) -admin.site.register(Tag) -admin.site.register(AnonymousCommentUser) +class PostTranslationInline(admin.StackedInline): + model = PostTranslation + extra = 1 + fields = ("language", "title", "body") + + +class CategoryTranslationInline(admin.TabularInline): + model = CategoryTranslation + extra = 1 + fields = ("language", "name", "description") + + +class TagTranslationInline(admin.TabularInline): + model = TagTranslation + extra = 1 + fields = ("language", "name", "description") + + +class PostAdminForm(forms.ModelForm): + class Meta: + model = Post + fields = "__all__" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if self.instance.weblog_id: + self.fields["category"].queryset = Category.objects.filter( + weblog=self.instance.weblog + ) + self.fields["tags"].queryset = Tag.objects.filter( + weblog=self.instance.weblog + ) + + +from django.utils.safestring import mark_safe + + [email protected](Post) +class PostAdmin(admin.ModelAdmin): + class CommentInline(admin.TabularInline): + model = Comment + extra = 0 + readonly_fields = ( + "comment_display", + "user_display", + "created_at", + "edited", + "edited_at", + ) + fields = ("comment_display", "user_display", "created_at", "edited") + exclude = ("body", "user", "anonymous_user", "level", "parent") + can_delete = False + max_num = 0 + + def user_display(self, obj): + if obj.user: + return mark_safe( + f'<a href="/admin/advanced/auth/user/{obj.user.id}/">{obj.user.username}</a>' + ) + elif obj.anonymous_user: + return mark_safe( + f'<a href="/admin/advanced/blog/anonymouscommentuser/{obj.anonymous_user.id}/">' + f"Anonymous: {obj.anonymous_user.name}</a>" + ) + return "None" + + user_display.short_description = "User" + + def comment_display(self, obj): + return mark_safe( + f'<a href="/admin/advanced/blog/comment/{obj.id}/">{obj.body[:100]}{"..." if len(obj.body) > 100 else ""}</a>' + ) + + comment_display.short_description = "Comment" + + form = PostAdminForm + list_display = ( + "title", + "weblog", + "author", + "date", + "is_public", + "views", + "comment_count", + ) + list_filter = ("weblog", "is_public", "category", "tags") + search_fields = ("title", "body") + prepopulated_fields = {"slug": ("title",)} + inlines = [PostTranslationInline, CommentInline] + date_hierarchy = "date" + + def comment_count(self, obj): + return obj.comments.count() + + comment_count.short_description = "Comments" + + def get_form(self, request, obj=None, **kwargs): + form = super().get_form(request, obj, **kwargs) + if obj is None: + form.base_fields["category"].queryset = Category.objects.none() + form.base_fields["tags"].queryset = Tag.objects.none() + return form + + def formfield_for_foreignkey(self, db_field, request, **kwargs): + if db_field.name == "category" and request._obj_ is not None: + kwargs["queryset"] = Category.objects.filter(weblog=request._obj_.weblog) + return super().formfield_for_foreignkey(db_field, request, **kwargs) + + def get_queryset(self, request): + qs = super().get_queryset(request) + request._obj_ = None + return qs + + def get_object(self, request, object_id, from_field=None): + obj = super().get_object(request, object_id, from_field=from_field) + if obj: + request._obj_ = obj + return obj + + [email protected](Category) +class CategoryAdmin(admin.ModelAdmin): + list_display = ("name", "weblog", "created_at") + list_filter = ("weblog",) + search_fields = ("name", "description") + prepopulated_fields = {"slug": ("name",)} + inlines = [CategoryTranslationInline] + + [email protected](Tag) +class TagAdmin(admin.ModelAdmin): + list_display = ("name", "weblog", "created_at") + list_filter = ("weblog",) + search_fields = ("name", "description") + prepopulated_fields = {"slug": ("name",)} + inlines = [TagTranslationInline] + + [email protected](Weblog) +class WeblogAdmin(admin.ModelAdmin): + class PostInline(admin.TabularInline): + model = Post + extra = 0 + readonly_fields = ("title", "author", "date", "is_public", "views") + can_delete = False + fields = ("title", "author", "date", "is_public", "views") + + def has_add_permission(self, request, obj=None): + return False + + class CategoryInline(admin.TabularInline): + model = Category + extra = 0 + readonly_fields = ("name", "created_at") + can_delete = False + fields = ("name", "created_at") + + def has_add_permission(self, request, obj=None): + return False + + class TagInline(admin.TabularInline): + model = Tag + extra = 0 + readonly_fields = ("name", "created_at") + can_delete = False + fields = ("name", "created_at") + + def has_add_permission(self, request, obj=None): + return False + + list_display = ("name", "owner", "created_at") + search_fields = ("name", "description") + prepopulated_fields = {"slug": ("name",)} + inlines = [PostInline, CategoryInline, TagInline] + + [email protected](Comment) +class CommentAdmin(admin.ModelAdmin): + list_display = ("post", "get_author", "created_at", "edited") + list_filter = ("edited", "created_at") + search_fields = ("body", "user__username", "anonymous_user__name") + readonly_fields = ("created_at", "edited", "edited_at") + + def get_author(self, obj): + return obj.user.username if obj.user else obj.anonymous_user.name + + get_author.short_description = "Author" + + [email protected](AnonymousCommentUser) +class AnonymousCommentUserAdmin(admin.ModelAdmin): + list_display = ("name", "email", "created_at") + search_fields = ("name", "email") + readonly_fields = ("created_at",) diff --git a/apps/blog/migrations/0019_posttranslation_weblog_alter_category_options_and_more.py b/apps/blog/migrations/0019_posttranslation_weblog_alter_category_options_and_more.py new file mode 100644 index 00000000..9faf4dc9 --- /dev/null +++ b/apps/blog/migrations/0019_posttranslation_weblog_alter_category_options_and_more.py @@ -0,0 +1,153 @@ +# Generated by Django 5.1.4 on 2025-01-02 04:27 + +import django.db.models.deletion +import django.utils.timezone +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0018_tag_name_ja'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='PostTranslation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('language', models.CharField(choices=[('en', 'English'), ('ja', 'Japanese'), ('es', 'Spanish'), ('fr', 'French'), ('de', 'German'), ('zh', 'Chinese'), ('ko', 'Korean')], max_length=2)), + ('title', models.CharField(max_length=100)), + ('body', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + ), + migrations.CreateModel( + name='Weblog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('slug', models.SlugField(unique=True)), + ('description', models.TextField(blank=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + ), + migrations.AlterModelOptions( + name='category', + options={'verbose_name_plural': 'Categories'}, + ), + migrations.AlterModelOptions( + name='comment', + options={'ordering': ['created_at']}, + ), + migrations.AddField( + model_name='anonymouscommentuser', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='comment', + name='level', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='comment', + name='parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='blog.comment'), + ), + migrations.AddField( + model_name='post', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='post', + name='updated_at', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='anonymouscommentuser', + name='avatar', + field=models.URLField(blank=True), + ), + migrations.AlterField( + model_name='anonymouscommentuser', + name='email', + field=models.CharField(max_length=32, unique=True), + ), + migrations.AlterField( + model_name='category', + name='slug', + field=models.SlugField(), + ), + migrations.AlterField( + model_name='comment', + name='post', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='blog.post'), + ), + migrations.AlterField( + model_name='post', + name='slug', + field=models.SlugField(max_length=100), + ), + migrations.AlterField( + model_name='tag', + name='slug', + field=models.SlugField(), + ), + migrations.AddIndex( + model_name='comment', + index=models.Index(fields=['post', 'created_at'], name='blog_commen_post_id_5fee65_idx'), + ), + migrations.AddIndex( + model_name='comment', + index=models.Index(fields=['parent', 'created_at'], name='blog_commen_parent__ffc1fe_idx'), + ), + migrations.AddField( + model_name='posttranslation', + name='post', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='blog.post'), + ), + migrations.AddField( + model_name='weblog', + name='owner', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='category', + name='weblog', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='blog.weblog'), + ), + migrations.AddField( + model_name='post', + name='weblog', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='blog.weblog'), + ), + migrations.AddField( + model_name='tag', + name='weblog', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='blog.weblog'), + ), + migrations.AlterUniqueTogether( + name='category', + unique_together={('weblog', 'slug')}, + ), + migrations.AlterUniqueTogether( + name='post', + unique_together={('weblog', 'slug')}, + ), + migrations.AlterUniqueTogether( + name='tag', + unique_together={('weblog', 'slug')}, + ), + migrations.AlterUniqueTogether( + name='posttranslation', + unique_together={('post', 'language')}, + ), + ] diff --git a/apps/blog/migrations/0020_alter_category_weblog_alter_post_weblog_and_more.py b/apps/blog/migrations/0020_alter_category_weblog_alter_post_weblog_and_more.py new file mode 100644 index 00000000..55e7f121 --- /dev/null +++ b/apps/blog/migrations/0020_alter_category_weblog_alter_post_weblog_and_more.py @@ -0,0 +1,32 @@ +# Generated by Django 5.1.4 on 2025-01-02 04:46 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0019_posttranslation_weblog_alter_category_options_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='category', + name='weblog', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='blog.weblog'), + preserve_default=False, + ), + migrations.AlterField( + model_name='post', + name='weblog', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='blog.weblog'), + preserve_default=False, + ), + migrations.AlterField( + model_name='tag', + name='weblog', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='blog.weblog'), + preserve_default=False, + ), + ] diff --git a/apps/blog/migrations/0021_categorytranslation_tagtranslation.py b/apps/blog/migrations/0021_categorytranslation_tagtranslation.py new file mode 100644 index 00000000..70e0a99e --- /dev/null +++ b/apps/blog/migrations/0021_categorytranslation_tagtranslation.py @@ -0,0 +1,44 @@ +# Generated by Django 5.1.4 on 2025-01-02 05:07 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0020_alter_category_weblog_alter_post_weblog_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='CategoryTranslation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('language', models.CharField(choices=[('en', 'English'), ('ja', 'Japanese'), ('es', 'Spanish'), ('fr', 'French'), ('de', 'German'), ('zh', 'Chinese'), ('ko', 'Korean')], max_length=2)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=50)), + ('description', models.TextField(blank=True)), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='blog.category')), + ], + options={ + 'unique_together': {('category', 'language')}, + }, + ), + migrations.CreateModel( + name='TagTranslation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('language', models.CharField(choices=[('en', 'English'), ('ja', 'Japanese'), ('es', 'Spanish'), ('fr', 'French'), ('de', 'German'), ('zh', 'Chinese'), ('ko', 'Korean')], max_length=2)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=50)), + ('description', models.TextField(blank=True)), + ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='blog.tag')), + ], + options={ + 'unique_together': {('tag', 'language')}, + }, + ), + ] diff --git a/apps/blog/models.py b/apps/blog/models.py index b4d791e2..9fa7eb30 100755 --- a/apps/blog/models.py +++ b/apps/blog/models.py @@ -1,114 +1,240 @@ import hashlib - +from bs4 import BeautifulSoup from django.conf import settings from django.db import models from django.utils.text import slugify UPLOAD_ROOT = "images/" +LANGUAGE_CHOICES = [ + ("en", "English"), + ("ja", "Japanese"), + ("es", "Spanish"), + ("fr", "French"), + ("de", "German"), + ("zh", "Chinese"), + ("ko", "Korean"), +] -# Create your models here. -class Category(models.Model): +class Translation(models.Model): + """Base abstract model for translations""" + + language = models.CharField(max_length=2, choices=LANGUAGE_CHOICES) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + abstract = True + + +class CategoryTranslation(Translation): + category = models.ForeignKey( + "Category", on_delete=models.CASCADE, related_name="translations" + ) name = models.CharField(max_length=50) - name_ja = models.CharField(max_length=50, blank=True) + description = models.TextField(blank=True) + + class Meta: + unique_together = ["category", "language"] + + def __str__(self): + return f"{self.category.name} - {self.get_language_display()}" + + +class TagTranslation(Translation): + tag = models.ForeignKey( + "Tag", on_delete=models.CASCADE, related_name="translations" + ) + name = models.CharField(max_length=50) + description = models.TextField(blank=True) + + class Meta: + unique_together = ["tag", "language"] + + +class PostTranslation(Translation): + post = models.ForeignKey( + "Post", on_delete=models.CASCADE, related_name="translations" + ) + title = models.CharField(max_length=100) + body = models.TextField() + + class Meta: + unique_together = ["post", "language"] + + +class TranslatableMixin: + 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) slug = models.SlugField(unique=True) description = models.TextField(blank=True) + owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) def save(self, *args, **kwargs): - if not self.slug or self.slug == "": + if not self.slug: self.slug = slugify(self.name) - return super(Category, self).save(*args, **kwargs) + super().save(*args, **kwargs) def __str__(self): return self.name +class Category(models.Model): + weblog = models.ForeignKey(Weblog, on_delete=models.CASCADE) + name = models.CharField(max_length=50) + name_ja = models.CharField( + max_length=50, blank=True + ) # Kept for backward compatibility + slug = models.SlugField() + description = models.TextField(blank=True) + created_at = models.DateTimeField(auto_now_add=True) + + class Meta: + unique_together = ["weblog", "slug"] + verbose_name_plural = "Categories" + + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(self.name) + super().save(*args, **kwargs) + + def __str__(self): + return f"{self.weblog.name} - {self.name}" + + def get_name(self, language_code="en"): + return self.translate("name", language_code) + + class Tag(models.Model): + weblog = models.ForeignKey(Weblog, on_delete=models.CASCADE) name = models.CharField(max_length=50) - name_ja = models.CharField(max_length=50, blank=True) - slug = models.SlugField(unique=True) + name_ja = models.CharField( + max_length=50, blank=True + ) # Kept for backward compatibility + slug = models.SlugField() description = models.TextField(blank=True) created_at = models.DateTimeField(auto_now_add=True) + class Meta: + unique_together = ["weblog", "slug"] + def save(self, *args, **kwargs): - if not self.slug or self.slug == "": + if not self.slug: self.slug = slugify(self.name) - return super(Tag, self).save(*args, **kwargs) + super().save(*args, **kwargs) def __str__(self): - return self.name + return f"{self.weblog.name} - {self.name}" + + def get_name(self, language_code="en"): + return self.translate("name", language_code) class Post(models.Model): + weblog = models.ForeignKey(Weblog, on_delete=models.CASCADE) title = models.CharField(max_length=100) - title_ja = models.CharField(max_length=100, blank=True) - slug = models.SlugField(max_length=100, unique=True) + title_ja = models.CharField( + max_length=100, blank=True + ) # Kept for backward compatibility + slug = models.SlugField(max_length=100) body = models.TextField(blank=True) - body_ja = models.TextField(blank=True) - date = models.DateTimeField(auto_now_add=False) - post_image = models.ImageField( - upload_to="{}/cover_images".format(UPLOAD_ROOT), blank=True - ) + body_ja = models.TextField(blank=True) # Kept for backward compatibility + date = models.DateTimeField() + post_image = models.ImageField(upload_to=f"{UPLOAD_ROOT}/cover_images", blank=True) image_url = models.URLField(blank=True) - author = models.ForeignKey( - settings.AUTH_USER_MODEL, - on_delete=models.CASCADE, - ) - category = models.ForeignKey( - "Category", - on_delete=models.CASCADE, - ) - tags = models.ManyToManyField("Tag", blank=True) + author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + category = models.ForeignKey(Category, on_delete=models.CASCADE) + tags = models.ManyToManyField(Tag, blank=True) is_public = models.BooleanField(default=False) views = models.IntegerField(default=0) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + unique_together = ["weblog", "slug"] def save(self, *args, **kwargs): - if not self.slug or self.slug == "": + if not self.slug: self.slug = slugify(self.title) - return super(Post, self).save(*args, **kwargs) + super().save(*args, **kwargs) def __str__(self): - return str(self.title) + 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 class AnonymousCommentUser(models.Model): name = models.CharField(max_length=32) - email = models.CharField(max_length=32) + email = models.CharField(max_length=32, unique=True) token = models.CharField(max_length=128, unique=True) - avatar = models.CharField(max_length=128, blank=True) + avatar = models.URLField(max_length=200, blank=True) + created_at = models.DateTimeField(auto_now_add=True) @classmethod def get_or_create(cls, email, token, avatar=""): email_hash = hashlib.md5(email.encode("utf-8")).hexdigest() token_hash = hashlib.sha256(token.encode("utf-8")).hexdigest() - return cls(email=email_hash, token=token_hash, avatar=avatar) + obj, created = cls.objects.get_or_create( + email_hash=email_hash, defaults={"token_hash": token_hash, "avatar": avatar} + ) + return obj def __str__(self): - return self.name + "(" + self.email + ")" + return f"{self.name} ({self.email[:8]})" class Comment(models.Model): - post = models.ForeignKey( - "Post", - on_delete=models.CASCADE, - ) + post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="comments") user = models.ForeignKey( - settings.AUTH_USER_MODEL, - on_delete=models.CASCADE, - blank=True, - null=True, + settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True ) anonymous_user = models.ForeignKey( - "AnonymousCommentUser", - on_delete=models.CASCADE, - blank=True, - null=True, + AnonymousCommentUser, on_delete=models.CASCADE, blank=True, null=True + ) + parent = models.ForeignKey( + "self", on_delete=models.CASCADE, null=True, blank=True, related_name="replies" ) body = models.TextField() created_at = models.DateTimeField(auto_now_add=True) edited = models.BooleanField(default=False) edited_at = models.DateTimeField(blank=True, null=True) + level = models.IntegerField(default=0) + + class Meta: + ordering = ["created_at"] + indexes = [ + models.Index(fields=["post", "created_at"]), + models.Index(fields=["parent", "created_at"]), + ] + + def save(self, *args, **kwargs): + if self.parent: + self.level = self.parent.level + 1 + super().save(*args, **kwargs) def __str__(self): - return self.body[:50] + "..." if len(self.body) > 50 else self.body + return f"{self.post.title} - {self.body[:50]}..." diff --git a/apps/blog/views.py b/apps/blog/views.py index 41610927..f590ee2b 100755 --- a/apps/blog/views.py +++ b/apps/blog/views.py @@ -1,11 +1,29 @@ from django.http import HttpResponseNotFound from django.shortcuts import render -from apps.blog.models import Post +from apps.blog.models import Post, Comment +from internal.weblog_utilities import highlight_code +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) + return render(request, "shared/blog/single_weblog.html", {"post": post}) except Post.DoesNotExist: return HttpResponseNotFound() diff --git a/apps/core/views.py b/apps/core/views.py index abe1d539..6b68b8bf 100755 --- a/apps/core/views.py +++ b/apps/core/views.py @@ -28,10 +28,9 @@ def my_journals(request): META = { "title": "My Journals", } - LANGUAGE_CODE = i18npatterns(request.LANGUAGE_CODE) request.meta.update(META) journals = Journal.objects.filter(owner=request.user).order_by("-created_at") context = { "journals": journals, } - return render(request, f"{LANGUAGE_CODE}/core/my/journals.html", context) + return render(request, f"shared/my/journals.html", context) diff --git a/apps/journals/views.py b/apps/journals/views.py index 070c20b0..797db38f 100755 --- a/apps/journals/views.py +++ b/apps/journals/views.py @@ -7,14 +7,13 @@ def journal_of_random_thoughts(request): META = { "title": "Journal: Journal of Random Thoughts", } - LANGUAGE_CODE = i18npatterns(request.LANGUAGE_CODE) request.meta.update(META) slug = "journal-of-random-thoughts" journal = Journal.objects.get(slug=slug) context = { "journal": journal, } - return render(request, f"{LANGUAGE_CODE}/journals/single.html", context) + return render(request, f"shared/journals/single.html", context) def single_journal(request, slug): @@ -25,9 +24,8 @@ def single_journal(request, slug): META = { "title": f"Journal: {journal.name}" if journal else "Journal Not Found", } - LANGUAGE_CODE = i18npatterns(request.LANGUAGE_CODE) request.meta.update(META) context = { "journal": journal, } - return render(request, f"{LANGUAGE_CODE}/journals/single.html", context) + return render(request, f"shared/journals/single.html", context) |
