Files
xingrin/backend/apps/targets/models.py

116 lines
4.3 KiB
Python
Raw Normal View History

2025-12-12 18:04:57 +08:00
from django.db import models
from django.utils import timezone
class SoftDeleteManager(models.Manager):
"""软删除管理器:默认只返回未删除的记录"""
def get_queryset(self):
return super().get_queryset().filter(deleted_at__isnull=True)
class Organization(models.Model):
"""组织模型"""
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=300, blank=True, default='', help_text='组织名称')
description = models.CharField(max_length=1000, blank=True, default='', help_text='组织描述')
created_at = models.DateTimeField(auto_now_add=True, help_text='创建时间')
# ==================== 软删除字段 ====================
deleted_at = models.DateTimeField(null=True, blank=True, db_index=True, help_text='删除时间NULL表示未删除')
targets = models.ManyToManyField(
'Target',
related_name='organizations',
blank=True,
help_text='所属目标列表'
)
# ==================== 管理器 ====================
objects = SoftDeleteManager() # 默认管理器:只返回未删除的记录
all_objects = models.Manager() # 全量管理器:包括已删除的记录(用于硬删除)
class Meta:
db_table = 'organization'
verbose_name = '组织'
verbose_name_plural = '组织'
ordering = ['-created_at']
# 部分唯一约束:只对未删除记录生效
constraints = [
models.UniqueConstraint(
fields=['name'],
condition=models.Q(deleted_at__isnull=True),
name='unique_organization_name_active'
),
]
indexes = [
models.Index(fields=['-created_at']),
models.Index(fields=['deleted_at', '-created_at']), # 软删除 + 时间索引
models.Index(fields=['name']), # 优化 name 搜索
]
def __str__(self):
return str(self.name or f'Organization {self.id}')
class Target(models.Model):
"""扫描目标模型
核心模型存储要扫描的目标信息
支持多种类型域名IP地址CIDR范围等
"""
# ==================== 类型定义 ====================
class TargetType(models.TextChoices):
DOMAIN = 'domain', '域名'
IP = 'ip', 'IP地址'
CIDR = 'cidr', 'CIDR范围'
# ==================== 基本字段 ====================
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=300, blank=True, default='', help_text='目标标识(域名/IP/CIDR')
type = models.CharField(
max_length=20,
choices=TargetType.choices,
default=TargetType.DOMAIN,
db_index=True,
help_text='目标类型'
)
# ==================== 时间戳 ====================
created_at = models.DateTimeField(auto_now_add=True, help_text='创建时间')
last_scanned_at = models.DateTimeField(null=True, blank=True, help_text='最后扫描时间')
# ==================== 软删除字段 ====================
deleted_at = models.DateTimeField(null=True, blank=True, db_index=True, help_text='删除时间NULL表示未删除')
# ==================== 管理器 ====================
objects = SoftDeleteManager() # 默认管理器:只返回未删除的记录
all_objects = models.Manager() # 全量管理器:包括已删除的记录(用于硬删除)
class Meta:
db_table = 'target'
verbose_name = '扫描目标'
verbose_name_plural = '扫描目标'
ordering = ['-created_at']
# 部分唯一约束:只对未删除记录生效
constraints = [
models.UniqueConstraint(
fields=['name'],
condition=models.Q(deleted_at__isnull=True),
name='unique_target_name_active'
),
]
indexes = [
models.Index(fields=['type']),
models.Index(fields=['-created_at']),
models.Index(fields=['deleted_at', '-created_at']), # 软删除 + 时间索引
models.Index(fields=['deleted_at', 'type']), # 软删除 + 类型索引
models.Index(fields=['name']), # 优化 name 搜索
]
def __str__(self):
return str(self.name or f'Target {self.id}')