mirror of
https://github.com/yyhuni/xingrin.git
synced 2026-01-31 19:53:11 +08:00
116 lines
4.3 KiB
Python
116 lines
4.3 KiB
Python
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}')
|