from django.contrib import admin from mptt.admin import DraggableMPTTAdmin from polymorphic.admin import ( PolymorphicChildModelAdmin, PolymorphicParentModelAdmin, PolymorphicChildModelFilter, PolymorphicInlineSupportMixin, StackedPolymorphicInline ) from .models import ( Item, BOMNode, EntityType, WorkCenter, BaseOperation, LaserCutSheet, LaserCutTube, Turning, Weld, Paint, Coating ) from django import forms # создаем форму с фильтром для dxf и dwg файлов class LaserCutSheetForm(forms.ModelForm): class Meta: model = LaserCutSheet fields = '__all__' widgets = { 'dxf_file': forms.FileInput(attrs={'accept': '.dxf,.DXF'}), } # создаем форму с фильтром для iges и igs файлов class LaserCutTubeForm(forms.ModelForm): class Meta: model = LaserCutTube fields = '__all__' widgets = { 'iges_file': forms.FileInput(attrs={'accept': '.iges,.IGS'}), } # --- 1. ИНЛАЙНЫ ДЛЯ ОПЕРАЦИЙ (ДЛЯ КАРТОЧКИ ITEM) --- class LaserCutSheetInline(StackedPolymorphicInline.Child): model = LaserCutSheet form = LaserCutSheetForm class LaserCutTubeInline(StackedPolymorphicInline.Child): model = LaserCutTube form = LaserCutTubeForm class TurningInline(StackedPolymorphicInline.Child): model = Turning class WeldInline(StackedPolymorphicInline.Child): model = Weld class PaintInline(StackedPolymorphicInline.Child): model = Paint class BaseOperationInline(StackedPolymorphicInline): model = BaseOperation child_inlines = ( LaserCutSheetInline, LaserCutTubeInline, TurningInline, WeldInline, PaintInline, ) # --- 2. ДОЧЕРНИЕ АДМИНКИ (НУЖНЫ ДЛЯ РАБОТЫ ПОЛИМОРФИЗМА) --- @admin.register(LaserCutSheet) class LaserCutSheetAdmin(PolymorphicChildModelAdmin): base_model = BaseOperation form = LaserCutSheetForm @admin.register(LaserCutTube) class LaserCutTubeAdmin(PolymorphicChildModelAdmin): base_model = BaseOperation form = LaserCutTubeForm @admin.register(Turning) class TurningAdmin(PolymorphicChildModelAdmin): base_model = BaseOperation @admin.register(Weld) class WeldAdmin(PolymorphicChildModelAdmin): base_model = BaseOperation @admin.register(Paint) class PaintAdmin(PolymorphicChildModelAdmin): base_model = BaseOperation # --- 3. РОДИТЕЛЬСКАЯ АДМИНКА ОПЕРАЦИЙ --- @admin.register(BaseOperation) class BaseOperationParentAdmin(PolymorphicParentModelAdmin): base_model = BaseOperation # Здесь указываем именно МОДЕЛИ, а не классы админок child_models = (LaserCutSheet, LaserCutTube, Turning, Weld, Paint) list_filter = (PolymorphicChildModelFilter,) list_display = ('item', 'order', 'polymorphic_ctype') # --- 4. ИНЛАЙН ДЛЯ BOM (СОСТАВ ИЗДЕЛИЯ) --- class BOMNodeInline(admin.TabularInline): model = BOMNode # fk_name = 'parent' fields = ('item', 'quantity') extra = 1 autocomplete_fields = ['item'] def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "parent": kwargs["queryset"] = BOMNode.objects.filter( item__entity_type__in=[EntityType.UNIT, EntityType.ASSEMBLY, EntityType.COMPLEX] ) return super().formfield_for_foreignkey(db_field, request, **kwargs) # --- 5. ОСНОВНАЯ АДМИНКА КОМПОНЕНТА (ITEM) --- @admin.register(Item) class ItemAdmin(PolymorphicInlineSupportMixin, admin.ModelAdmin): list_display = ('get_full_name', 'entity_type', 'drawing') list_filter = ('entity_type', 'is_assembly') search_fields = ['designation', 'title'] @admin.display(description='Наименование') def get_full_name(self, obj): return f"{obj.designation or ''} {obj.title}".strip() # Добавляем оба инлайна: и состав, и техпроцесс inlines = [BOMNodeInline, BaseOperationInline] # --- 6. АДМИНКА ДЛЯ ДЕРЕВА BOM --- @admin.register(BOMNode) class BOMNodeAdmin(DraggableMPTTAdmin): mptt_level_indent = 40 fields = ('parent', 'item', 'quantity') list_display = ('tree_actions', 'indented_title', 'get_designation', 'quantity') list_display_links = ('indented_title',) def get_designation(self, obj): return obj.item.designation get_designation.short_description = 'Децимальный номер' def get_queryset(self, request): return super().get_queryset(request).select_related('item', 'parent') def get_inlines(self, request, obj=None): if obj and obj.item.entity_type in [EntityType.UNIT, EntityType.ASSEMBLY, EntityType.COMPLEX]: return [BOMNodeInline] return [] # --- 7. ПРОЧИЕ СПРАВОЧНИКИ --- @admin.register(WorkCenter) class WorkCenterAdmin(admin.ModelAdmin): list_display = ('name', 'rate_per_hour') @admin.register(Coating) class CoatingAdmin(admin.ModelAdmin): list_display = ('name', 'consumption')