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)