Files
xingrin/backend/apps/targets/models.py
2025-12-12 18:04:57 +08:00

116 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}')