Features: 1) Add I18NFieldsetMixin to organize translation fields into a dedicated fieldset; 2) Implement I18NTabTranslationAdmin for enhanced multi-language admin support; 3) Apply new translation admin to AttributeGroupAdmin, AttributeAdmin, AttributeValueAdmin, CategoryAdmin, BrandAdmin, ProductAdmin, ProductTagAdmin, CategoryTagAdmin, and PromotionAdmin.
Fixes: 1) Replace `TranslationGenericTabularInline` with `I18NTabTranslationAdmin` to avoid potential translation field duplication. Extra: 1) Update fieldsets in various model admins for improved structure and translation field grouping; 2) Add constants for fieldset section names to enhance readability and consistency.
This commit is contained in:
parent
02102fa470
commit
48ef110ac4
1 changed files with 155 additions and 32 deletions
187
core/admin.py
187
core/admin.py
|
|
@ -5,9 +5,14 @@ from django.apps import apps
|
|||
from django.contrib import admin
|
||||
from django.contrib.admin import ModelAdmin, TabularInline
|
||||
from django.contrib.gis.admin import GISModelAdmin
|
||||
from django.db.models import Model
|
||||
from django.urls import path
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from modeltranslation.admin import TranslationGenericTabularInline
|
||||
from modeltranslation.admin import (
|
||||
TabbedExternalJqueryTranslationAdmin,
|
||||
)
|
||||
from modeltranslation.translator import translator
|
||||
from modeltranslation.utils import get_translation_fields
|
||||
from mptt.admin import DraggableMPTTAdmin
|
||||
|
||||
from evibes.settings import CONSTANCE_CONFIG
|
||||
|
|
@ -34,6 +39,51 @@ from .models import (
|
|||
Wishlist,
|
||||
)
|
||||
|
||||
SECTION_GENERAL = _("general")
|
||||
SECTION_I18N = _("I18N")
|
||||
SECTION_META = _("metadata")
|
||||
SECTION_DATES = _("timestamps")
|
||||
SECTION_RELATIONS = _("relations")
|
||||
|
||||
|
||||
class I18NFieldsetMixin:
|
||||
model: type[Model]
|
||||
"""
|
||||
Pulls all <field>_<lang> translation columns out of the regular
|
||||
fieldsets and tucks them into one extra fieldset/tab called "I18N".
|
||||
"""
|
||||
|
||||
def get_fieldsets(self, request, obj=None):
|
||||
base_fieldsets = super().get_fieldsets(request, obj)
|
||||
|
||||
trans_opts = translator.get_options_for_model(self.model)
|
||||
translation_fields = []
|
||||
for orig in trans_opts.fields.keys(): # noqa: SIM118
|
||||
translation_fields.extend(get_translation_fields(orig))
|
||||
|
||||
cleaned = []
|
||||
for title, opts in base_fieldsets:
|
||||
original = list(opts.get("fields", []))
|
||||
filtered = [f for f in original if f not in translation_fields]
|
||||
opts = opts.copy()
|
||||
opts["fields"] = filtered
|
||||
cleaned.append((title, opts))
|
||||
|
||||
cleaned.append(
|
||||
(
|
||||
_("I18N"),
|
||||
{
|
||||
"classes": ("suit-tab-i18n",),
|
||||
"fields": tuple(translation_fields),
|
||||
},
|
||||
)
|
||||
)
|
||||
return cleaned
|
||||
|
||||
|
||||
class I18NTabTranslationAdmin(I18NFieldsetMixin, TabbedExternalJqueryTranslationAdmin):
|
||||
pass
|
||||
|
||||
|
||||
class BasicModelAdmin(ModelAdmin):
|
||||
@admin.action(description=str(_("activate selected %(verbose_name_plural)s")))
|
||||
|
|
@ -71,16 +121,41 @@ class AttributeValueInline(TabularInline):
|
|||
|
||||
|
||||
@admin.register(AttributeGroup)
|
||||
class AttributeGroupAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
||||
class AttributeGroupAdmin(BasicModelAdmin, I18NTabTranslationAdmin):
|
||||
list_display = ("name", "modified")
|
||||
search_fields = (
|
||||
"uuid",
|
||||
"name",
|
||||
)
|
||||
fieldsets = (
|
||||
(
|
||||
SECTION_GENERAL,
|
||||
{
|
||||
"fields": ("name", "parent", "is_active"),
|
||||
},
|
||||
),
|
||||
(
|
||||
SECTION_META,
|
||||
{
|
||||
"fields": ("uuid",),
|
||||
},
|
||||
),
|
||||
(
|
||||
SECTION_I18N,
|
||||
{
|
||||
"classes": ("suit-tab-i18n",),
|
||||
"fields": tuple( # pulled in by I18NFieldsetMixin
|
||||
translator.get_options_for_model(
|
||||
AttributeGroup
|
||||
).get_all_translation_fields()
|
||||
),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@admin.register(Attribute)
|
||||
class AttributeAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
||||
class AttributeAdmin(BasicModelAdmin, I18NTabTranslationAdmin):
|
||||
list_display = ("name", "group", "value_type", "modified")
|
||||
list_filter = ("value_type", "group", "is_active")
|
||||
search_fields = ("uuid", "name", "group__name")
|
||||
|
|
@ -88,7 +163,7 @@ class AttributeAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
|||
|
||||
|
||||
@admin.register(AttributeValue)
|
||||
class AttributeValueAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
||||
class AttributeValueAdmin(BasicModelAdmin, I18NTabTranslationAdmin):
|
||||
list_display = ("attribute", "value", "modified")
|
||||
list_filter = ("attribute__group", "is_active")
|
||||
search_fields = ("uuid", "value", "attribute__name")
|
||||
|
|
@ -104,7 +179,7 @@ class CategoryChildrenInline(admin.TabularInline):
|
|||
|
||||
|
||||
@admin.register(Category)
|
||||
class CategoryAdmin(DraggableMPTTAdmin, BasicModelAdmin, TranslationGenericTabularInline):
|
||||
class CategoryAdmin(DraggableMPTTAdmin, BasicModelAdmin, I18NTabTranslationAdmin):
|
||||
mptt_indent_field = "name"
|
||||
list_display = ("indented_title", "parent", "is_active", "modified")
|
||||
# noinspection PyUnresolvedReferences
|
||||
|
|
@ -115,25 +190,48 @@ class CategoryAdmin(DraggableMPTTAdmin, BasicModelAdmin, TranslationGenericTabul
|
|||
"name",
|
||||
)
|
||||
inlines = [CategoryChildrenInline]
|
||||
fieldsets = [
|
||||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
SECTION_GENERAL,
|
||||
{
|
||||
"fields": (
|
||||
"uuid",
|
||||
"slug",
|
||||
"name",
|
||||
"description",
|
||||
"slug",
|
||||
"parent",
|
||||
"is_active",
|
||||
"priority",
|
||||
"image",
|
||||
"markup_percent",
|
||||
"tags",
|
||||
)
|
||||
),
|
||||
},
|
||||
)
|
||||
]
|
||||
),
|
||||
(
|
||||
SECTION_RELATIONS,
|
||||
{
|
||||
"fields": ("tags",),
|
||||
},
|
||||
),
|
||||
(
|
||||
SECTION_META,
|
||||
{
|
||||
"fields": ("uuid",),
|
||||
},
|
||||
),
|
||||
(
|
||||
SECTION_DATES,
|
||||
{
|
||||
"fields": ("created", "modified"),
|
||||
},
|
||||
),
|
||||
(
|
||||
SECTION_I18N,
|
||||
{
|
||||
"classes": ("suit-tab-i18n",),
|
||||
"fields": tuple(
|
||||
translator.get_options_for_model(
|
||||
Category
|
||||
).get_all_translation_fields()
|
||||
),
|
||||
},
|
||||
),
|
||||
)
|
||||
autocomplete_fields = ["parent", "tags"]
|
||||
readonly_fields = (
|
||||
"uuid",
|
||||
|
|
@ -148,7 +246,7 @@ class CategoryAdmin(DraggableMPTTAdmin, BasicModelAdmin, TranslationGenericTabul
|
|||
|
||||
|
||||
@admin.register(Brand)
|
||||
class BrandAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
||||
class BrandAdmin(BasicModelAdmin, I18NTabTranslationAdmin):
|
||||
list_display = ("name",)
|
||||
list_filter = ("categories", "is_active")
|
||||
search_fields = (
|
||||
|
|
@ -179,7 +277,7 @@ class StockInline(TabularInline):
|
|||
|
||||
|
||||
@admin.register(Product)
|
||||
class ProductAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
||||
class ProductAdmin(BasicModelAdmin, I18NTabTranslationAdmin):
|
||||
list_display = (
|
||||
"name",
|
||||
"partnumber",
|
||||
|
|
@ -224,23 +322,46 @@ class ProductAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
|||
|
||||
fieldsets = (
|
||||
(
|
||||
_("basic info"),
|
||||
SECTION_GENERAL,
|
||||
{
|
||||
"fields": (
|
||||
"uuid",
|
||||
"name",
|
||||
"slug",
|
||||
"partnumber",
|
||||
"is_active",
|
||||
"is_digital",
|
||||
"name",
|
||||
"category",
|
||||
"brand",
|
||||
"description",
|
||||
"tags",
|
||||
)
|
||||
),
|
||||
},
|
||||
),
|
||||
(
|
||||
SECTION_RELATIONS,
|
||||
{
|
||||
"fields": ("category", "brand", "tags"),
|
||||
},
|
||||
),
|
||||
(
|
||||
SECTION_META,
|
||||
{
|
||||
"fields": ("uuid",),
|
||||
},
|
||||
),
|
||||
(
|
||||
SECTION_DATES,
|
||||
{
|
||||
"fields": ("created", "modified"),
|
||||
},
|
||||
),
|
||||
(
|
||||
SECTION_I18N,
|
||||
{
|
||||
"classes": ("suit-tab-i18n",),
|
||||
"fields": tuple(
|
||||
translator.get_options_for_model(
|
||||
Product
|
||||
).get_all_translation_fields()
|
||||
),
|
||||
},
|
||||
),
|
||||
(_("important dates"), {"fields": ("created", "modified")}),
|
||||
)
|
||||
|
||||
inlines = [AttributeValueInline, ProductImageInline, StockInline]
|
||||
|
|
@ -252,13 +373,13 @@ class ProductAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
|||
|
||||
|
||||
@admin.register(ProductTag)
|
||||
class ProductTagAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
||||
class ProductTagAdmin(BasicModelAdmin, I18NTabTranslationAdmin):
|
||||
list_display = ("name",)
|
||||
search_fields = ("name",)
|
||||
|
||||
|
||||
@admin.register(CategoryTag)
|
||||
class CategoryTagAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
||||
class CategoryTagAdmin(BasicModelAdmin, I18NTabTranslationAdmin):
|
||||
list_display = ("name",)
|
||||
search_fields = ("name",)
|
||||
|
||||
|
|
@ -370,7 +491,7 @@ class PromoCodeAdmin(BasicModelAdmin):
|
|||
|
||||
|
||||
@admin.register(Promotion)
|
||||
class PromotionAdmin(BasicModelAdmin, TranslationGenericTabularInline):
|
||||
class PromotionAdmin(BasicModelAdmin, I18NTabTranslationAdmin):
|
||||
list_display = ("name", "discount_percent", "modified")
|
||||
search_fields = ("name",)
|
||||
autocomplete_fields = ("products",)
|
||||
|
|
@ -433,7 +554,9 @@ class ConstanceAdmin(BaseConstanceAdmin):
|
|||
self.admin_site.admin_view(self.changelist_view),
|
||||
name=f"{info}_changelist",
|
||||
),
|
||||
path("", self.admin_site.admin_view(self.changelist_view), name=f"{info}_add"),
|
||||
path(
|
||||
"", self.admin_site.admin_view(self.changelist_view), name=f"{info}_add"
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue