schon/core/admin.py
Egor fureunoir Gorbunov d9e67d5de3 Fixes: None;
Features: None;

Extra: 1) Change fieldset titles to lowercase for consistency.
2025-06-22 16:34:57 +03:00

442 lines
13 KiB
Python

from constance.admin import Config
from constance.admin import ConstanceAdmin as BaseConstanceAdmin
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.utils.translation import gettext_lazy as _
from modeltranslation.translator import translator
from modeltranslation.utils import get_translation_fields
from mptt.admin import DraggableMPTTAdmin
from evibes.settings import CONSTANCE_CONFIG
from .forms import OrderForm, OrderProductForm, VendorForm
from .models import (
Address,
Attribute,
AttributeGroup,
AttributeValue,
Brand,
Category,
CategoryTag,
Feedback,
Order,
OrderProduct,
Product,
ProductImage,
ProductTag,
PromoCode,
Promotion,
Stock,
Vendor,
Wishlist,
)
class TranslationFieldsetMixin:
model: Model
def get_fieldsets(self, request, obj=None):
fieldsets = super().get_fieldsets(request, obj)
opts = translator.get_options_for_model(self.model)
translation_fields = []
for orig in opts.local_fields:
translation_fields += get_translation_fields(orig)
if translation_fields:
fieldsets = list(fieldsets) + [
(_("translations"), {"fields": translation_fields})
]
return fieldsets
class FieldsetsMixin:
general_fields = []
relation_fields = []
model: Model
def get_fieldsets(self, request, obj=None):
fieldsets = []
if self.general_fields:
fieldsets.append((_("general"), {"fields": self.general_fields}))
if self.relation_fields:
fieldsets.append((_("relations"), {"fields": self.relation_fields}))
opts = self.model._meta
if any(f.name == "uuid" for f in opts.fields):
fieldsets.append((_("metadata"), {"fields": ["uuid"]}))
ts = []
for name in ("created", "modified"):
if any(f.name == name for f in opts.fields):
ts.append(name)
if ts:
fieldsets.append((_("timestamps"), {"fields": ts, "classes": ["collapse"]}))
return fieldsets
class BasicModelAdmin(ModelAdmin):
@admin.action(description=str(_("activate selected %(verbose_name_plural)s")))
def activate_selected(self, _request, queryset) -> str:
queryset.update(is_active=True)
return str(_("%(verbose_name_plural)s activated successfully!"))
@admin.action(description=str(_("deactivate selected %(verbose_name_plural)s")))
def deactivate_selected(self, _request, queryset) -> str:
queryset.update(is_active=False)
return str(_("%(verbose_name_plural)s deactivated successfully."))
def get_actions(self, request):
actions = super().get_actions(request)
actions["activate_selected"] = (
self.activate_selected,
"activate_selected",
str(_("activate selected %(verbose_name_plural)s")),
)
actions["deactivate_selected"] = (
self.deactivate_selected,
"deactivate_selected",
str(_("deactivate selected %(verbose_name_plural)s")),
)
return actions
class AttributeValueInline(TabularInline):
model = AttributeValue
extra = 0
autocomplete_fields = ["attribute"]
class ProductImageInline(TabularInline):
model = ProductImage
extra = 0
class StockInline(TabularInline):
model = Stock
extra = 0
class OrderProductInline(TabularInline):
model = OrderProduct
extra = 0
readonly_fields = ("product", "quantity", "buy_price")
form = OrderProductForm
def get_queryset(self, request):
return (
super()
.get_queryset(request)
.select_related("product")
.only("product__name")
)
class CategoryChildrenInline(TabularInline):
model = Category
fk_name = "parent"
extra = 0
fields = ("name", "description", "is_active", "image", "markup_percent")
@admin.register(AttributeGroup)
class AttributeGroupAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = AttributeGroup
list_display = ("name", "modified")
search_fields = ("uuid", "name")
general_fields = ["name", "parent"]
relation_fields = []
@admin.register(Attribute)
class AttributeAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = Attribute
list_display = ("name", "group", "value_type", "modified")
list_filter = ("value_type", "group", "is_active")
search_fields = ("uuid", "name", "group__name")
autocomplete_fields = ["categories", "group"]
general_fields = ["name", "value_type"]
relation_fields = ["group", "categories"]
@admin.register(AttributeValue)
class AttributeValueAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = AttributeValue
list_display = ("attribute", "value", "modified")
list_filter = ("attribute__group", "is_active")
search_fields = ("uuid", "value", "attribute__name")
autocomplete_fields = ["attribute"]
general_fields = ["value"]
relation_fields = ["attribute", "product"]
@admin.register(Category)
class CategoryAdmin(
FieldsetsMixin, TranslationFieldsetMixin, DraggableMPTTAdmin, BasicModelAdmin
):
model = Category
list_display = ("indented_title", "parent", "is_active", "modified")
list_filter = ("is_active", "level", "created", "modified")
search_fields = ("uuid", "name")
inlines = [CategoryChildrenInline]
autocomplete_fields = ["parent", "tags"]
readonly_fields = ("slug",)
general_fields = ["name", "description", "image", "markup_percent"]
relation_fields = ["parent", "tags"]
@admin.register(Brand)
class BrandAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = Brand
list_display = ("name",)
list_filter = ("categories", "is_active")
search_fields = ("uuid", "name", "categories__name")
general_fields = ["name", "description"]
relation_fields = ["small_logo", "big_logo", "categories"]
@admin.register(Product)
class ProductAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = Product
list_display = (
"name",
"partnumber",
"is_active",
"category",
"brand",
"price",
"rating",
"modified",
)
list_filter = (
"is_active",
"is_digital",
("tags", admin.RelatedOnlyFieldListFilter),
("stocks__vendor", admin.RelatedOnlyFieldListFilter),
"created",
"modified",
)
search_fields = (
"name",
"partnumber",
"brand__name",
"category__name",
"uuid",
"slug",
)
readonly_fields = ("slug",)
autocomplete_fields = ("category", "brand", "tags")
inlines = [AttributeValueInline, ProductImageInline, StockInline]
general_fields = ["name", "partnumber", "is_active", "is_digital"]
relation_fields = ["category", "brand", "tags"]
@admin.register(ProductTag)
class ProductTagAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = ProductTag
list_display = ("tag_name",)
search_fields = ("tag_name",)
general_fields = ["tag_name", "name"]
relation_fields = []
@admin.register(CategoryTag)
class CategoryTagAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = CategoryTag
list_display = ("tag_name",)
search_fields = ("tag_name",)
general_fields = ["tag_name", "name"]
relation_fields = []
@admin.register(Vendor)
class VendorAdmin(FieldsetsMixin, BasicModelAdmin):
model = Vendor
list_display = ("name", "markup_percent", "modified")
list_filter = ("markup_percent", "is_active")
search_fields = ("name",)
form = VendorForm
general_fields = ["name", "markup_percent", "authentication"]
relation_fields = []
@admin.register(Feedback)
class FeedbackAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = Feedback
list_display = ("order_product", "rating", "comment", "modified")
list_filter = ("rating", "is_active")
search_fields = ("order_product__product__name", "comment")
general_fields = ["rating", "comment"]
relation_fields = ["order_product"]
@admin.register(Order)
class OrderAdmin(FieldsetsMixin, BasicModelAdmin):
model = Order
list_display = (
"human_readable_id",
"user",
"status",
"total_price",
"buy_time",
"modified",
)
list_filter = ("status", "buy_time", "modified", "created")
search_fields = ("user__email", "status", "uuid", "human_readable_id")
readonly_fields = ("total_price", "total_quantity", "human_readable_id")
inlines = [OrderProductInline]
form = OrderForm
general_fields = ["user", "status"]
relation_fields = ["promo_code", "billing_address", "shipping_address"]
@admin.register(OrderProduct)
class OrderProductAdmin(FieldsetsMixin, BasicModelAdmin):
model = OrderProduct
list_display = ("order", "product", "quantity", "buy_price", "status", "modified")
list_filter = ("status",)
search_fields = ("order__user__email", "product__name")
form = OrderProductForm
general_fields = ["quantity", "buy_price", "status"]
relation_fields = ["order", "product"]
@admin.register(PromoCode)
class PromoCodeAdmin(FieldsetsMixin, BasicModelAdmin):
model = PromoCode
list_display = (
"code",
"discount_percent",
"discount_amount",
"start_time",
"end_time",
"used_on",
)
list_filter = ("discount_percent", "discount_amount", "start_time", "end_time")
search_fields = ("code",)
general_fields = ["code", "discount_amount", "discount_percent"]
relation_fields = ["user"]
@admin.register(Promotion)
class PromotionAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = Promotion
list_display = ("name", "discount_percent", "modified")
search_fields = ("name",)
autocomplete_fields = ("products",)
general_fields = ["name", "discount_percent", "description"]
relation_fields = ["products"]
@admin.register(Stock)
class StockAdmin(FieldsetsMixin, BasicModelAdmin):
model = Stock
list_display = ("product", "vendor", "sku", "quantity", "price", "modified")
list_filter = ("vendor", "quantity")
search_fields = ("product__name", "vendor__name", "sku")
autocomplete_fields = ("product", "vendor")
general_fields = ["sku", "quantity", "price", "purchase_price", "digital_asset"]
relation_fields = ["product", "vendor"]
@admin.register(Wishlist)
class WishlistAdmin(FieldsetsMixin, BasicModelAdmin):
model = Wishlist
list_display = ("user", "modified")
search_fields = ("user__email",)
general_fields = ["user"]
relation_fields = ["products"]
@admin.register(ProductImage)
class ProductImageAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin):
model = ProductImage
list_display = ("alt", "product", "priority", "modified")
list_filter = ("priority",)
search_fields = ("alt", "product__name")
autocomplete_fields = ("product",)
general_fields = ["alt", "priority", "image"]
relation_fields = ["product"]
@admin.register(Address)
class AddressAdmin(FieldsetsMixin, GISModelAdmin):
model = Address
list_display = ("street", "city", "region", "country", "user")
list_filter = ("country", "region")
search_fields = ("street", "city", "postal_code", "user__email")
gis_widget_kwargs = {
"attrs": {
"default_lon": 37.61556,
"default_lat": 55.75222,
"default_zoom": 6,
}
}
general_fields = [
"address_line",
"street",
"district",
"city",
"region",
"postal_code",
"country",
"raw_data",
]
relation_fields = ["user", "api_response"]
# Constance configuration
class ConstanceConfig:
class Meta:
app_label = "core"
object_name = "Config"
concrete_model = None
model_name = module_name = "config"
verbose_name_plural = _("Config")
abstract = False
swapped = False
is_composite_pk = False
def get_change_permission(self):
return f"change_{self.model_name}"
@property
def app_config(self):
return apps.get_app_config(self.app_label)
@property
def label(self):
return f"{self.app_label}.{self.object_name}"
@property
def label_lower(self):
return f"{self.app_label}.{self.model_name}"
def get_ordered_objects(self):
return False
_meta = Meta()
admin.site.unregister([Config])
admin.site.register([ConstanceConfig], BaseConstanceAdmin)
admin.site.site_title = CONSTANCE_CONFIG["PROJECT_NAME"][0]
admin.site.site_header = "eVibes"
admin.site.index_title = CONSTANCE_CONFIG["PROJECT_NAME"][0]