from django.contrib import admin from django.contrib.admin.actions import delete_selected from django.urls import reverse from django.utils.html import format_html from .models import Branch, EquipmentImage, Drawing, PublicScreen from .models import Activity, Branch, Event, Contact, VideoTerminal, Budget, EquipmentBudget, InfrastructureBudget, BudgetTemplate, TemplateEquipmentItem, TemplateInfrastructureItem from django_select2.forms import Select2Widget from unfold.admin import ModelAdmin from django.contrib.admin import AdminSite from django.contrib.auth.models import User, Group from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin from django.db.models import Count, Q from django.utils.html import format_html from django.urls import reverse from django import forms # 定义Activity的内联admin类 class ActivityInline(admin.TabularInline): # 改为更紧凑的表格形式内联(原StackedInline为堆叠形式) model = Activity extra = 1 # 在Branch表单中默认显示1个额外的Activity表单(可根据需求调整数值) fields = ('name', 'scope', 'start_time', 'end_time') # 限制内联表单显示的字段 readonly_fields = ('start_time',) # 可选:将开始时间设为只读字段(避免误修改) # 可选:添加帮助文本提示 help_texts = { 'name': '请输入活动名称(必填)', 'scope': '选择活动范围(内部/外部)' } admin.site.unregister(User) admin.site.unregister(Group) @admin.register(User) class UserAdmin(BaseUserAdmin, ModelAdmin): pass @admin.register(Group) class GroupAdmin(BaseGroupAdmin, ModelAdmin): pass @admin.register(Branch) class BranchAdmin(ModelAdmin): inlines = [ActivityInline] list_display = ('name', 'location', 'category', 'display_mature_status', 'background_color') search_fields = ['name', 'location'] fieldsets = ( (None, { 'fields': ('name', 'location', 'contact_info', 'description', 'category', 'is_mature', 'background_color') }), ) def display_mature_status(self, obj): return '💼' if obj.is_mature else '📒' display_mature_status.short_description = '是否成熟' def activity_count(self, obj): return obj.activity_set.count() activity_count.short_description = '活动数量' def get_queryset(self, request): queryset = super().get_queryset(request) queryset = queryset.annotate( inspection_person_count=Count('contact', filter=Q(contact__category='机房/设备间巡检人'))) return queryset actions = ['set_branches_to_type_b'] def set_branches_to_type_b(self, request, queryset): queryset.update(category='B型') set_branches_to_type_b.short_description = '将选中的分支机构统一改为B型' # 注册Activity模型(如果需要的话,虽然在这个示例中我们主要关注Branch) @admin.register(Activity) class ActivityAdmin(ModelAdmin): list_display = ('branch', 'scope', 'name', 'start_time', 'end_time') search_fields = ["branch__name"] # 改为关联Branch模型的name字段 add_form_template = 'admin/huodong/add_form.html' autocomplete_fields = ['branch'] @admin.register(Event) class EventAdmin(ModelAdmin): list_display = ('name', 'start_time', 'end_time', 'description') filter_horizontal = ('branches',) class ContactAdminForm(forms.ModelForm): class Meta: model = Contact fields = '__all__' widgets = { # 使用复选框实现多选 'category': forms.CheckboxSelectMultiple(choices=Contact.CATEGORY_CHOICES) } class EquipmentImageAdmin(admin.ModelAdmin): def bulk_delete_selected(self, request, queryset): count = queryset.count() queryset.delete() self.message_user(request, f'已成功删除{count}条设备图片记录') bulk_delete_selected.short_description = '批量删除选中的设备图片' actions = ['bulk_delete_selected'] list_display = ['id', 'branch', 'uploaded_at', 'delete_link'] def delete_link(self, obj): url = reverse('admin:huodong_equipmentimage_delete', args=[obj.id]) return format_html('删除', url) delete_link.short_description = '操作' list_filter = ['branch'] search_fields = ['branch__name'] autocomplete_fields = ['branch'] def get_form(self, request, obj=None, **kwargs): form = super().get_form(request, obj, **kwargs) # 设置默认分支机构为最后一个设备间图片的分支机构 try: latest_image = EquipmentImage.objects.latest('uploaded_at') form.base_fields['branch'].initial = latest_image.branch_id except EquipmentImage.DoesNotExist: pass return form def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) # Count images for the current branch count = EquipmentImage.objects.filter(branch=obj.branch).count() self.message_user(request, f"【{obj.branch.name}】已经有{count}张设备间图片。") admin.site.register(EquipmentImage, EquipmentImageAdmin) class DrawingAdmin(admin.ModelAdmin): def bulk_delete_selected(self, request, queryset): count = queryset.count() queryset.delete() self.message_user(request, f'已成功删除{count}条图纸记录') bulk_delete_selected.short_description = '批量删除选中的图纸' actions = ['bulk_delete_selected'] list_display = ('id', 'branch', 'uploaded_at', 'delete_link') def delete_link(self, obj): url = reverse('admin:huodong_drawing_delete', args=[obj.id]) return format_html('删除', url) delete_link.short_description = '操作' list_filter = ('branch', 'uploaded_at') search_fields = ('branch__name',) autocomplete_fields = ['branch'] admin.site.register(Drawing, DrawingAdmin) class PublicScreenAdmin(ModelAdmin): def delete_link(self, obj): if obj.id: delete_url = reverse('admin:huodong_publicscreen_delete', args=[obj.id]) return format_html('删除', delete_url) return '-' delete_link.short_description = '操作' def bulk_delete_selected(self, request, queryset): count = queryset.count() queryset.delete() self.message_user(request, f'已成功删除{count}条公共电子屏记录') bulk_delete_selected.short_description = '批量删除选中的公共电子屏' list_display = ('id', 'branch', 'screen_type', 'last_drill', 'delete_link') list_filter = ['branch', 'screen_type'] autocomplete_fields = ['branch'] actions = ['bulk_delete_selected'] admin.site.register(PublicScreen, PublicScreenAdmin) @admin.register(Contact) class ContactAdmin(ModelAdmin): form = ContactAdminForm # 指定自定义表单 list_display = ('branch', 'category', 'name', 'phone', 'email') # 可选:显示分类字段 autocomplete_fields = ['branch'] @admin.register(VideoTerminal) class VideoTerminalAdmin(ModelAdmin): list_display = ('branch', 'terminal_type', 'description', 'created_at') list_filter = ('terminal_type', 'branch') search_fields = ('branch__name', 'description') autocomplete_fields = ['branch'] # 预算相关Admin配置 # 设备预算内联 class EquipmentBudgetInline(admin.TabularInline): model = EquipmentBudget extra = 1 fields = ('project', 'model', 'unit_price', 'procurement_method', 'quantity', 'subtotal') readonly_fields = ('subtotal',) # 小计自动计算,设为只读 # 基础设施预算内联 class InfrastructureBudgetInline(admin.TabularInline): model = InfrastructureBudget extra = 1 fields = ('name', 'remarks', 'unit_price', 'unit', 'quantity', 'subtotal', 'description') readonly_fields = ('subtotal',) # 小计自动计算,设为只读 # 预算Admin @admin.register(Budget) class BudgetAdmin(ModelAdmin): list_display = ('branch', 'name', 'total_budget', 'created_at') list_filter = ('branch',) search_fields = ('branch__name', 'name') autocomplete_fields = ['branch'] readonly_fields = ('total_budget',) # 总预算自动计算,设为只读 inlines = [EquipmentBudgetInline, InfrastructureBudgetInline] def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) # 保存后重新计算总预算 obj.update_total_budget() # 设备预算Admin(如果需要单独管理) @admin.register(EquipmentBudget) class EquipmentBudgetAdmin(ModelAdmin): list_display = ('budget', 'project', 'model', 'unit_price', 'procurement_method', 'quantity', 'subtotal') list_filter = ('budget__branch', 'project', 'procurement_method') search_fields = ('budget__branch__name', 'project', 'model') autocomplete_fields = ['budget'] readonly_fields = ('subtotal',) # 基础设施预算Admin(如果需要单独管理) @admin.register(InfrastructureBudget) class InfrastructureBudgetAdmin(ModelAdmin): list_display = ('budget', 'name', 'unit_price', 'unit', 'quantity', 'subtotal') list_filter = ('budget__branch', 'name') search_fields = ('budget__branch__name', 'name', 'description') autocomplete_fields = ['budget'] readonly_fields = ('subtotal',) # 预算模板相关Admin配置 # 模板设备项内联 class TemplateEquipmentItemInline(admin.TabularInline): model = TemplateEquipmentItem extra = 1 # 模板基础设施项内联 class TemplateInfrastructureItemInline(admin.TabularInline): model = TemplateInfrastructureItem extra = 1 # 模板设备项Admin(如果需要单独管理) @admin.register(TemplateEquipmentItem) class TemplateEquipmentItemAdmin(ModelAdmin): list_display = ('template', 'project', 'model', 'unit_price', 'procurement_method') list_filter = ('template', 'project', 'procurement_method') search_fields = ('template__name', 'project', 'model') autocomplete_fields = ['template'] # 模板基础设施项Admin(如果需要单独管理) @admin.register(TemplateInfrastructureItem) class TemplateInfrastructureItemAdmin(ModelAdmin): list_display = ('template', 'name', 'unit_price', 'unit') list_filter = ('template', 'unit') search_fields = ('template__name', 'name', 'description') autocomplete_fields = ['template'] # 预算模板Admin @admin.register(BudgetTemplate) class BudgetTemplateAdmin(ModelAdmin): list_display = ('name', 'description', 'is_default', 'created_at') list_filter = ('is_default',) search_fields = ('name', 'description') inlines = [TemplateEquipmentItemInline, TemplateInfrastructureItemInline] def save_model(self, request, obj, form, change): # 如果设置为默认模板,将其他模板的默认状态取消 if obj.is_default: BudgetTemplate.objects.exclude(id=obj.id).update(is_default=False) super().save_model(request, obj, form, change)