diff --git a/core/admin.py b/core/admin.py index 4c63f113..566a5eec 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,4 +1,3 @@ -# noinspection PyUnresolvedReferences from constance.admin import Config from constance.admin import ConstanceAdmin as BaseConstanceAdmin from django.apps import apps @@ -46,13 +45,32 @@ class TranslationFieldsetMixin: for orig in opts.local_fields: translation_fields += get_translation_fields(orig) if translation_fields: - fieldsets = list(fieldsets) - fieldsets.append( - ( - _("translations"), - {"fields": 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 @@ -85,29 +103,17 @@ class BasicModelAdmin(ModelAdmin): class AttributeValueInline(TabularInline): model = AttributeValue extra = 0 - is_navtab = True - verbose_name = _("attribute value") - verbose_name_plural = _("attribute values") autocomplete_fields = ["attribute"] - icon = "fa-regular fa-circle-dot" class ProductImageInline(TabularInline): model = ProductImage extra = 0 - is_navtab = True - verbose_name = _("image") - verbose_name_plural = _("images") - icon = "fa-regular fa-images" class StockInline(TabularInline): model = Stock extra = 0 - is_navtab = True - verbose_name = _("stock") - verbose_name_plural = _("stocks") - icon = "fa-regular fa-boxes-stacked" class OrderProductInline(TabularInline): @@ -115,10 +121,6 @@ class OrderProductInline(TabularInline): extra = 0 readonly_fields = ("product", "quantity", "buy_price") form = OrderProductForm - is_navtab = True - verbose_name = _("order product") - verbose_name_plural = _("order products") - icon = "fa-regular fa-circle-dot" def get_queryset(self, request): return ( @@ -134,60 +136,72 @@ class CategoryChildrenInline(TabularInline): fk_name = "parent" extra = 0 fields = ("name", "description", "is_active", "image", "markup_percent") - icon = "fa-regular fa-circle-dot" -# Admin registrations @admin.register(AttributeGroup) -class AttributeGroupAdmin(TranslationFieldsetMixin, BasicModelAdmin): +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(TranslationFieldsetMixin, BasicModelAdmin): +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(TranslationFieldsetMixin, BasicModelAdmin): +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(TranslationFieldsetMixin, DraggableMPTTAdmin, BasicModelAdmin): - mptt_indent_field = "name" +class CategoryAdmin( + FieldsetsMixin, TranslationFieldsetMixin, DraggableMPTTAdmin, BasicModelAdmin +): + model = Category list_display = ("indented_title", "parent", "is_active", "modified") list_filter = ("is_active", "level", "created", "modified") - list_display_links = ("indented_title",) search_fields = ("uuid", "name") inlines = [CategoryChildrenInline] autocomplete_fields = ["parent", "tags"] - readonly_fields = ("uuid", "slug", "created", "modified") + readonly_fields = ("slug",) - def indented_title(self, instance): - return instance.name - - indented_title.short_description = _("name") - indented_title.admin_order_field = "name" + general_fields = ["name", "description", "image", "markup_percent"] + relation_fields = ["parent", "tags"] @admin.register(Brand) -class BrandAdmin(TranslationFieldsetMixin, BasicModelAdmin): +class BrandAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin): + model = Brand list_display = ("name",) list_filter = ("categories", "is_active") search_fields = ("uuid", "name", "categories__name") - readonly_fields = ("uuid", "slug") + + general_fields = ["name", "description"] + relation_fields = ["small_logo", "big_logo", "categories"] @admin.register(Product) -class ProductAdmin(TranslationFieldsetMixin, BasicModelAdmin): +class ProductAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin): + model = Product list_display = ( "name", "partnumber", @@ -214,68 +228,63 @@ class ProductAdmin(TranslationFieldsetMixin, BasicModelAdmin): "uuid", "slug", ) - readonly_fields = ("created", "modified", "uuid", "rating", "price", "slug") + readonly_fields = ("slug",) autocomplete_fields = ("category", "brand", "tags") - fieldsets = ( - ( - "general", - {"fields": ("name", "slug", "partnumber", "is_active", "is_digital")}, - ), - ("relations", {"fields": ("category", "brand", "tags")}), - ("metadata", {"fields": ("uuid",)}), - ("timestamps", {"fields": ("created", "modified")}), - ) inlines = [AttributeValueInline, ProductImageInline, StockInline] - def price(self, obj): - return obj.price - - price.short_description = _("price") - - def rating(self, obj): - return obj.rating - - rating.short_description = _("rating") - - def get_changelist(self, request, **kwargs): - cl = super().get_changelist(request, **kwargs) - cl.filter_input_length = 64 - return cl + general_fields = ["name", "partnumber", "is_active", "is_digital"] + relation_fields = ["category", "brand", "tags"] @admin.register(ProductTag) -class ProductTagAdmin(TranslationFieldsetMixin, BasicModelAdmin): - list_display = ("name",) - search_fields = ("name",) +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(TranslationFieldsetMixin, BasicModelAdmin): - list_display = ("name",) - search_fields = ("name",) +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(BasicModelAdmin): +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(TranslationFieldsetMixin, BasicModelAdmin): +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(BasicModelAdmin): +class OrderAdmin(FieldsetsMixin, BasicModelAdmin): + model = Order list_display = ( "human_readable_id", "user", - "is_business", "status", "total_price", "buy_time", @@ -283,56 +292,29 @@ class OrderAdmin(BasicModelAdmin): ) list_filter = ("status", "buy_time", "modified", "created") search_fields = ("user__email", "status", "uuid", "human_readable_id") - readonly_fields = ("total_price", "total_quantity", "buy_time", "human_readable_id") + readonly_fields = ("total_price", "total_quantity", "human_readable_id") inlines = [OrderProductInline] form = OrderForm - def is_business(self, obj): - return obj.is_business - - is_business.short_description = _("is business") - - def get_queryset(self, request): - return ( - super() - .get_queryset(request) - .prefetch_related( - "user", - "shipping_address", - "billing_address", - "order_products", - "promo_code", - ) - ) - - def save_model(self, request, obj, form, change): - if form.cleaned_data.get("attributes") is None: - obj.attributes = None - if form.cleaned_data.get("notifications") is None: - obj.notifications = None - super().save_model(request, obj, form, change) + general_fields = ["user", "status"] + relation_fields = ["promo_code", "billing_address", "shipping_address"] @admin.register(OrderProduct) -class OrderProductAdmin(BasicModelAdmin): +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 - def get_queryset(self, request): - return super().get_queryset(request).prefetch_related("order", "product") - - def save_model(self, request, obj, form, change): - if form.cleaned_data.get("attributes") is None: - obj.attributes = None - if form.cleaned_data.get("notifications") is None: - obj.notifications = None - super().save_model(request, obj, form, change) + general_fields = ["quantity", "buy_price", "status"] + relation_fields = ["order", "product"] @admin.register(PromoCode) -class PromoCodeAdmin(BasicModelAdmin): +class PromoCodeAdmin(FieldsetsMixin, BasicModelAdmin): + model = PromoCode list_display = ( "code", "discount_percent", @@ -344,54 +326,61 @@ class PromoCodeAdmin(BasicModelAdmin): list_filter = ("discount_percent", "discount_amount", "start_time", "end_time") search_fields = ("code",) - def get_queryset(self, request): - return super().get_queryset(request).prefetch_related("user") + general_fields = ["code", "discount_amount", "discount_percent"] + relation_fields = ["user"] @admin.register(Promotion) -class PromotionAdmin(TranslationFieldsetMixin, BasicModelAdmin): +class PromotionAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin): + model = Promotion list_display = ("name", "discount_percent", "modified") search_fields = ("name",) autocomplete_fields = ("products",) - def get_queryset(self, request): - return super().get_queryset(request).prefetch_related("products") + general_fields = ["name", "discount_percent", "description"] + relation_fields = ["products"] @admin.register(Stock) -class StockAdmin(BasicModelAdmin): +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(BasicModelAdmin): +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(TranslationFieldsetMixin, BasicModelAdmin): +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(GISModelAdmin): +class AddressAdmin(FieldsetsMixin, GISModelAdmin): + model = Address list_display = ("street", "city", "region", "country", "user") list_filter = ("country", "region") - search_fields = ( - "raw_data", - "street", - "city", - "postal_code", - "user__email", - "address_line", - ) + search_fields = ("street", "city", "postal_code", "user__email") gis_widget_kwargs = { "attrs": { "default_lon": 37.61556, @@ -400,15 +389,27 @@ class AddressAdmin(GISModelAdmin): } } + general_fields = [ + "address_line", + "street", + "district", + "city", + "region", + "postal_code", + "country", + "raw_data", + ] + relation_fields = ["user", "api_response"] -# Constance config + +# Constance configuration class ConstanceConfig: class Meta: app_label = "core" object_name = "Config" concrete_model = None model_name = module_name = "config" - verbose_name_plural = _("config") + verbose_name_plural = _("Config") abstract = False swapped = False is_composite_pk = False @@ -436,6 +437,6 @@ class ConstanceConfig: admin.site.unregister([Config]) admin.site.register([ConstanceConfig], BaseConstanceAdmin) -admin.site.site_title = f"{CONSTANCE_CONFIG.get('PROJECT_NAME')[0]}" +admin.site.site_title = CONSTANCE_CONFIG["PROJECT_NAME"][0] admin.site.site_header = "eVibes" -admin.site.index_title = f"{CONSTANCE_CONFIG.get('PROJECT_NAME')[0]}" +admin.site.index_title = CONSTANCE_CONFIG["PROJECT_NAME"][0]