diff --git a/assets/admin.py b/assets/admin.py index ea5d68b7..7d9b667e 100644 --- a/assets/admin.py +++ b/assets/admin.py @@ -1,3 +1,193 @@ from django.contrib import admin +from django import forms +from assets.models import Assets, ServerAssets, NetworkAssets, OfficeAssets, SecurityAssets, StorageAssets, SoftwareAssets, DiskAssets, RamAssets, NetworkCardAssets, AssetProvider, IDC, Cabinet, AdminRecord, ZabbixAlert, WebSite, BusinessLine, PullAssetConf -# Register your models here. + +class BusinessLineForm(forms.ModelForm): + class Meta: + model = BusinessLine + fields = '__all__' + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if self.instance and self.instance.pk: + exclude_ids = [self.instance.pk] + [child.pk for child in self.instance.get_all_children()] + self.fields['parent'].queryset = BusinessLine.objects.exclude(pk__in=exclude_ids) + + +class BusinessLineAdmin(admin.ModelAdmin): + form = BusinessLineForm + list_display = ('name', 'parent', 'level', 'sort', 'get_full_path', 'memo') + list_filter = ('level', 'parent') + search_fields = ('name', 'memo') + ordering = ('sort', 'id') + list_editable = ('sort',) + + def get_full_path(self, obj): + return obj.get_full_path() + get_full_path.short_description = '完整路径' + + def save_model(self, request, obj, form, change): + if obj.parent: + obj.level = obj.parent.level + 1 + else: + obj.level = 1 + super().save_model(request, obj, form, change) + + +class AssetsAdmin(admin.ModelAdmin): + list_display = ('asset_type', 'asset_nu', 'asset_model', 'asset_status', 'asset_management_ip', + 'asset_admin', 'business_line_display', 'business_owner_display', 'asset_idc', 'asset_cabinet') + list_filter = ('asset_type', 'asset_status', 'asset_admin', 'asset_idc', 'asset_business_line', 'asset_business_owner') + search_fields = ('asset_nu', 'asset_model', 'asset_management_ip') + readonly_fields = ('asset_create_time', 'asset_update_time') + fieldsets = ( + ('基本信息', { + 'fields': ('asset_type', 'asset_nu', 'asset_model', 'asset_status', 'asset_memo') + }), + ('业务信息', { + 'fields': ('asset_business_line', 'asset_business_owner') + }), + ('管理信息', { + 'fields': ('asset_admin', 'asset_management_ip') + }), + ('位置信息', { + 'fields': ('asset_provider', 'asset_idc', 'asset_cabinet') + }), + ('财务信息', { + 'fields': ('asset_purchase_day', 'asset_expire_day', 'asset_price') + }), + ('时间信息', { + 'fields': ('asset_create_time', 'asset_update_time'), + 'classes': ('collapse',) + }), + ) + + def business_line_display(self, obj): + if obj.asset_business_line: + return obj.asset_business_line.get_full_path() + return '-' + business_line_display.short_description = '所属业务线' + + def business_owner_display(self, obj): + if obj.asset_business_owner: + return obj.asset_business_owner.username + return '-' + business_owner_display.short_description = '业务负责人' + + +class ServerAssetsAdmin(admin.ModelAdmin): + list_display = ('assets', 'server_type', 'hostname', 'system', 'system_version', 'port') + list_filter = ('server_type', 'system') + search_fields = ('hostname', 'assets__asset_nu', 'assets__asset_management_ip') + + +class NetworkAssetsAdmin(admin.ModelAdmin): + list_display = ('assets', 'network_type') + list_filter = ('network_type',) + search_fields = ('assets__asset_nu', 'assets__asset_management_ip') + + +class OfficeAssetsAdmin(admin.ModelAdmin): + list_display = ('assets', 'office_type') + list_filter = ('office_type',) + search_fields = ('assets__asset_nu', 'assets__asset_management_ip') + + +class SecurityAssetsAdmin(admin.ModelAdmin): + list_display = ('assets', 'security_type') + list_filter = ('security_type',) + search_fields = ('assets__asset_nu', 'assets__asset_management_ip') + + +class StorageAssetsAdmin(admin.ModelAdmin): + list_display = ('assets', 'storage_type') + list_filter = ('storage_type',) + search_fields = ('assets__asset_nu', 'assets__asset_management_ip') + + +class SoftwareAssetsAdmin(admin.ModelAdmin): + list_display = ('assets', 'software_type') + list_filter = ('software_type',) + search_fields = ('assets__asset_nu',) + + +class DiskAssetsAdmin(admin.ModelAdmin): + list_display = ('asset', 'disk_slot', 'disk_volume', 'disk_model', 'disk_brand', 'disk_status') + list_filter = ('disk_status', 'disk_brand') + search_fields = ('asset__asset_nu', 'disk_serial', 'disk_model') + + +class RamAssetsAdmin(admin.ModelAdmin): + list_display = ('asset', 'ram_slot', 'ram_volume', 'ram_brand', 'ram_serial') + list_filter = ('ram_brand',) + search_fields = ('asset__asset_nu', 'ram_serial') + + +class NetworkCardAssetsAdmin(admin.ModelAdmin): + list_display = ('asset', 'network_card_name', 'network_card_mac', 'network_card_ip', 'network_card_status') + list_filter = ('network_card_status',) + search_fields = ('asset__asset_nu', 'network_card_mac', 'network_card_ip') + + +class AssetProviderAdmin(admin.ModelAdmin): + list_display = ('asset_provider_name', 'asset_provider_contact', 'asset_provider_telephone', 'asset_provider_memo') + search_fields = ('asset_provider_name', 'asset_provider_contact') + + +class IDCAdmin(admin.ModelAdmin): + list_display = ('idc_name', 'idc_address', 'idc_contact', 'idc_telephone', 'idc_memo') + search_fields = ('idc_name', 'idc_address') + + +class CabinetAdmin(admin.ModelAdmin): + list_display = ('idc', 'cabinet_name', 'cabinet_memo') + list_filter = ('idc',) + search_fields = ('cabinet_name',) + + +class AdminRecordAdmin(admin.ModelAdmin): + list_display = ('admin_login_user', 'admin_server', 'admin_remote_ip', 'admin_start_time', + 'admin_login_status_time', 'admin_record_mode') + list_filter = ('admin_record_mode', 'admin_login_user') + search_fields = ('admin_server', 'admin_remote_ip') + readonly_fields = ('admin_login_user', 'admin_server', 'admin_remote_ip', 'admin_start_time', + 'admin_login_status_time', 'admin_record_mode', 'admin_record_file', 'admin_record_cmds') + + +class ZabbixAlertAdmin(admin.ModelAdmin): + list_display = ('alert_date', 'alert_num') + list_filter = ('alert_date',) + date_hierarchy = 'alert_date' + + +class WebSiteAdmin(admin.ModelAdmin): + list_display = ('web_name', 'web_address', 'web_des') + search_fields = ('web_name', 'web_address') + + +class PullAssetConfAdmin(admin.ModelAdmin): + list_display = ('conf_name', 'cloud_name', 'cloud_region', 'belong_user', 'server_user', 'server_port') + list_filter = ('cloud_name',) + search_fields = ('conf_name', 'cloud_region') + readonly_fields = ('access_key',) + + +admin.site.register(BusinessLine, BusinessLineAdmin) +admin.site.register(Assets, AssetsAdmin) +admin.site.register(ServerAssets, ServerAssetsAdmin) +admin.site.register(NetworkAssets, NetworkAssetsAdmin) +admin.site.register(OfficeAssets, OfficeAssetsAdmin) +admin.site.register(SecurityAssets, SecurityAssetsAdmin) +admin.site.register(StorageAssets, StorageAssetsAdmin) +admin.site.register(SoftwareAssets, SoftwareAssetsAdmin) +admin.site.register(DiskAssets, DiskAssetsAdmin) +admin.site.register(RamAssets, RamAssetsAdmin) +admin.site.register(NetworkCardAssets, NetworkCardAssetsAdmin) +admin.site.register(AssetProvider, AssetProviderAdmin) +admin.site.register(IDC, IDCAdmin) +admin.site.register(Cabinet, CabinetAdmin) +admin.site.register(AdminRecord, AdminRecordAdmin) +admin.site.register(ZabbixAlert, ZabbixAlertAdmin) +admin.site.register(WebSite, WebSiteAdmin) +admin.site.register(PullAssetConf, PullAssetConfAdmin) diff --git a/assets/models.py b/assets/models.py index 3427e1eb..4a27e85e 100644 --- a/assets/models.py +++ b/assets/models.py @@ -30,6 +30,10 @@ class Assets(models.Model): on_delete=models.PROTECT) asset_cabinet = models.ForeignKey('Cabinet', related_name='assets', null=True, blank=True, verbose_name='所在机柜', on_delete=models.PROTECT) + asset_business_line = models.ForeignKey('BusinessLine', related_name='assets', null=True, blank=True, + verbose_name='所属业务线', on_delete=models.SET_NULL) + asset_business_owner = models.ForeignKey('users.UserProfile', related_name='business_owner_assets', null=True, blank=True, + verbose_name='业务负责人', on_delete=models.SET_NULL) asset_purchase_day = models.DateField(null=True, blank=True, verbose_name="购买日期") asset_expire_day = models.DateField(null=True, blank=True, verbose_name="过保日期") @@ -295,6 +299,41 @@ class Meta: verbose_name_plural = '常用网站表' +class BusinessLine(models.Model): + """业务线(支持多级分类)""" + name = models.CharField(max_length=100, verbose_name='业务线名称') + parent = models.ForeignKey('self', related_name='children', null=True, blank=True, + verbose_name='父级业务线', on_delete=models.CASCADE) + level = models.SmallIntegerField(default=1, verbose_name='层级') + sort = models.SmallIntegerField(default=0, verbose_name='排序') + memo = models.TextField(null=True, blank=True, verbose_name='备注') + + class Meta: + db_table = 'ops_business_line' + verbose_name = '业务线表' + verbose_name_plural = '业务线表' + ordering = ['sort', 'id'] + + def __str__(self): + return self.get_full_path() + + def get_full_path(self): + """获取完整层级路径""" + path = [self.name] + parent = self.parent + while parent: + path.insert(0, parent.name) + parent = parent.parent + return '/'.join(path) + + def get_all_children(self): + """获取所有子业务线(包括嵌套的子业务线)""" + children = list(self.children.all()) + for child in self.children.all(): + children.extend(child.get_all_children()) + return children + + class PullAssetConf(models.Model): cloud_names = ( ('ali', '阿里云'), diff --git a/assets/views.py b/assets/views.py index 2962674c..f6c76556 100644 --- a/assets/views.py +++ b/assets/views.py @@ -77,12 +77,30 @@ def get_assets_charts(request): def get_assets_list(request): asset_types = Assets.asset_types asset_status = request.GET.get('asset_status') - assets = None + business_line_id = request.GET.get('business_line') + business_owner_id = request.GET.get('business_owner') + + assets = Assets.objects.select_related('serverassets', 'asset_business_line', 'asset_business_owner') + if asset_status: db_status = tuple(filter(lambda x: x[1] == asset_status, Assets.asset_status_))[0][0] - assets = Assets.objects.filter(asset_status=db_status) - else: - assets = Assets.objects.select_related('serverassets') + assets = assets.filter(asset_status=db_status) + + if business_line_id: + try: + business_line = BusinessLine.objects.get(id=business_line_id) + all_children = [business_line.id] + [child.id for child in business_line.get_all_children()] + assets = assets.filter(asset_business_line_id__in=all_children) + except BusinessLine.DoesNotExist: + pass + + if business_owner_id: + assets = assets.filter(asset_business_owner_id=business_owner_id) + + business_lines = BusinessLine.objects.filter(parent__isnull=True).prefetch_related('children') + all_business_lines = BusinessLine.objects.all() + business_owners = UserProfile.objects.all() + return render(request, 'assets/assets_list.html', locals()) @@ -101,6 +119,8 @@ def add_asset(request): asset_idcs = IDC.objects.all() asset_cabinets = Cabinet.objects.select_related('idc') server_assets = ServerAssets.objects.select_related('assets') + business_lines = BusinessLine.objects.all() + business_owners = UserProfile.objects.all() return render(request, 'assets/add_asset.html', locals()) diff --git a/templates/assets/add_asset.html b/templates/assets/add_asset.html index 1db0e1f9..6b7b507e 100644 --- a/templates/assets/add_asset.html +++ b/templates/assets/add_asset.html @@ -80,6 +80,28 @@ +