Features: 1) Add multilingual title and content fields to the Post model in blog; 2) Introduce translation registration for Post in a new blog/translation.py; 3) Enhance PostAdmin with mixins and readonly slug.

Fixes: 1) Fix shebangs in Docker entry-point scripts to use `/usr/bin/bash`.

Extra: 1) Refactor slug fields in `core` migrations for `Brand`, `Category`, and `Product`; 2) Cleanup and simplify admin code in `core/admin.py`.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-06-29 16:14:59 +03:00
parent e8c1c6daed
commit 97785b29db
8 changed files with 428 additions and 30 deletions

View file

@ -1,33 +1,31 @@
from django.contrib import admin from django.contrib import admin
from django_summernote.admin import SummernoteModelAdmin from django_summernote.admin import SummernoteModelAdminMixin
from core.admin import BasicModelAdmin, FieldsetsMixin
from .models import Post, PostTag from .models import Post, PostTag
@admin.register(Post) @admin.register(Post)
class PostAdmin(SummernoteModelAdmin): class PostAdmin(SummernoteModelAdminMixin, FieldsetsMixin, BasicModelAdmin):
list_display = ("title", "author", "slug", "created", "modified") list_display = ("title", "author", "slug", "created", "modified")
list_filter = ("author", "tags", "created", "modified") list_filter = ("author", "tags", "created", "modified")
search_fields = ("title", "content") search_fields = ("title", "content", "slug")
filter_horizontal = ("tags",) filter_horizontal = ("tags",)
date_hierarchy = "created" date_hierarchy = "created"
autocomplete_fields = ("author", "tags") autocomplete_fields = ("author", "tags")
summernote_fields = ("content",) readonly_fields = ("slug",)
fieldsets = ( summernote_fields = ("content",)
( general_fields = [
None,
{
"fields": (
"author",
"title", "title",
"author",
"content", "content",
"file", "file",
]
relation_fields = [
"tags", "tags",
) ]
},
),
)
@admin.register(PostTag) @admin.register(PostTag)

View file

@ -0,0 +1,338 @@
# Generated by Django 5.2 on 2025-06-29 13:09
import markdown_field.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("blog", "0003_alter_post_tags"),
]
operations = [
migrations.AddField(
model_name="post",
name="content_ar_ar",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_cs_cz",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_da_dk",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_de_de",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_en_gb",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_en_us",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_es_es",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_fr_fr",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_hi_in",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_it_it",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_ja_jp",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_kk_kz",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_nl_nl",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_pl_pl",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_pt_br",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_ro_ro",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_ru_ru",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="content_zh_hans",
field=markdown_field.fields.MarkdownField(
blank=True, null=True, verbose_name="content"
),
),
migrations.AddField(
model_name="post",
name="title_ar_ar",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_cs_cz",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_da_dk",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_de_de",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_en_gb",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_en_us",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_es_es",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_fr_fr",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_hi_in",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_it_it",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_ja_jp",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_kk_kz",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_nl_nl",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_pl_pl",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_pt_br",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_ro_ro",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_ru_ru",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
migrations.AddField(
model_name="post",
name="title_zh_hans",
field=models.CharField(
help_text="post title",
max_length=128,
null=True,
unique=True,
verbose_name="title",
),
),
]

9
blog/translation.py Normal file
View file

@ -0,0 +1,9 @@
from modeltranslation.decorators import register
from modeltranslation.translator import TranslationOptions
from blog.models import Post
@register(Post)
class PostOptions(TranslationOptions):
fields = ("title", "content")

View file

@ -52,9 +52,7 @@ class FieldsetsMixin:
for orig in transoptions.local_fields: for orig in transoptions.local_fields:
translation_fields += get_translation_fields(orig) translation_fields += get_translation_fields(orig)
if translation_fields: if translation_fields:
fss = list(fss) + [ fss = list(fss) + [(_("translations"), {"fields": translation_fields})]
(_("translations"), {"fields": translation_fields})
]
return fss return fss
if self.general_fields: if self.general_fields:
@ -148,12 +146,7 @@ class OrderProductInline(TabularInline):
icon = "fa-solid fa-boxes-packing" icon = "fa-solid fa-boxes-packing"
def get_queryset(self, request): def get_queryset(self, request):
return ( return super().get_queryset(request).select_related("product").only("product__name")
super()
.get_queryset(request)
.select_related("product")
.only("product__name")
)
class CategoryChildrenInline(TabularInline): class CategoryChildrenInline(TabularInline):

View file

@ -0,0 +1,60 @@
# Generated by Django 5.2 on 2025-06-29 13:09
import core.utils.db
import django_extensions.db.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("core", "0034_category_priority_alter_brand_priority"),
]
operations = [
migrations.AlterField(
model_name="brand",
name="slug",
field=django_extensions.db.fields.AutoSlugField(
allow_unicode=True,
blank=True,
editable=False,
max_length=88,
null=True,
overwrite=True,
populate_from=("name",),
unique=True,
verbose_name="Slug",
),
),
migrations.AlterField(
model_name="category",
name="slug",
field=core.utils.db.TweakedAutoSlugField(
allow_unicode=True,
blank=True,
editable=False,
max_length=88,
null=True,
overwrite=True,
populate_from=("parent__name", "name"),
unique=True,
verbose_name="Slug",
),
),
migrations.AlterField(
model_name="product",
name="slug",
field=django_extensions.db.fields.AutoSlugField(
allow_unicode=True,
blank=True,
editable=False,
max_length=88,
null=True,
overwrite=True,
populate_from=("name", "brand__slug", "category__slug", "uuid"),
unique=True,
verbose_name="Slug",
),
),
]

View file

@ -1,4 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/bash
set -e set -e
# wait for auxiliary services # wait for auxiliary services

View file

@ -1,4 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/bash
set -e set -e
# wait for auxiliary services # wait for auxiliary services

View file

@ -1,4 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/bash
set -e set -e
# wait for auxiliary services # wait for auxiliary services