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: list = [] relation_fields: list = [] 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") readonly_fields = ("uuid", "modified", "created") 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") readonly_fields = ("uuid", "modified", "created") 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") readonly_fields = ("uuid", "modified", "created") 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", "uuid", "modified", "created") 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") readonly_fields = ("uuid", "modified", "created") general_fields = ["name", "description"] relation_fields = ["small_logo", "big_logo", "categories"] @admin.register(Product) class ProductAdmin(FieldsetsMixin, TranslationFieldsetMixin, BasicModelAdmin): model = Product # type: ignore 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", "uuid", "modified", "created") 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",) readonly_fields = ("uuid", "modified", "created") 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",) readonly_fields = ("uuid", "modified", "created") 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",) readonly_fields = ("uuid", "modified", "created") 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") readonly_fields = ("uuid", "modified", "created") 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", "uuid", "modified", "created", ) 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") readonly_fields = ("uuid", "modified", "created") 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",) readonly_fields = ("uuid", "modified", "created") 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",) readonly_fields = ("uuid", "modified", "created") 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") readonly_fields = ("uuid", "modified", "created") 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",) readonly_fields = ("uuid", "modified", "created") 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") readonly_fields = ("uuid", "modified", "created") 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") readonly_fields = ("uuid", "modified", "created") 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]