operations_project/apps/knowledge_base/models.py
2025-05-21 12:32:20 +08:00

179 lines
6.6 KiB
Python

# apps/knowledge_base/models.py
from django.db import models
from django.utils import timezone
from django.core.exceptions import ValidationError
import uuid
from apps.accounts.models import User
class KnowledgeBase(models.Model):
"""知识库模型"""
KNOWLEDGE_BASE_TYPES = [
('admin', '管理级知识库'),
('leader', '部门级知识库'),
('member', '成员级知识库'),
('private', '私有知识库'),
('secret', '公司级别私密知识库'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user_id = models.UUIDField(verbose_name='创建者ID')
name = models.CharField(max_length=100, unique=True, verbose_name='知识库名称')
desc = models.TextField(verbose_name='知识库描述', null=True, blank=True)
type = models.CharField(
max_length=20,
choices=KNOWLEDGE_BASE_TYPES,
default='private',
verbose_name='知识库类型'
)
department = models.CharField(max_length=50, null=True, blank=True)
group = models.CharField(max_length=50, null=True, blank=True)
documents = models.JSONField(default=list)
char_length = models.IntegerField(default=0)
document_count = models.IntegerField(default=0)
external_id = models.UUIDField(null=True, blank=True)
create_time = models.DateTimeField(auto_now_add=True)
update_time = models.DateTimeField(auto_now=True)
def is_owner(self, user):
"""检查用户是否是所有者(通过权限表检查)"""
from apps.permissions.models import KnowledgeBasePermission
return str(user.id) == str(self.user_id) or KnowledgeBasePermission.objects.filter(
knowledge_base=self,
user=user,
can_read=True,
can_edit=True,
can_delete=True,
status='active'
).exists()
def get_owners(self):
"""获取所有所有者(包括创建者和具有完整权限的用户)"""
from apps.accounts.models import User
from apps.permissions.models import KnowledgeBasePermission
# 获取创建者
owners = [self.user_id]
# 获取具有完整权限的用户
permission_owners = KnowledgeBasePermission.objects.filter(
knowledge_base=self,
can_read=True,
can_edit=True,
can_delete=True,
status='active'
).values_list('user_id', flat=True)
owners.extend(permission_owners)
return User.objects.filter(id__in=set(owners))
def calculate_stats(self):
"""计算文档统计信息"""
total_chars = 0
doc_count = 0
if self.documents:
doc_count = len(self.documents)
for doc in self.documents:
if 'paragraphs' in doc:
for para in doc['paragraphs']:
if 'content' in para:
total_chars += len(para['content'])
if 'title' in para:
total_chars += len(para['title'])
return doc_count, total_chars
def save(self, *args, **kwargs):
"""重写保存方法"""
# 只在创建时计算统计信息
if not self.pk: # 如果是新实例
doc_count, char_count = self.calculate_stats()
self.document_count = doc_count
self.char_length = char_count
# 直接调用Model的save方法
models.Model.save(self, *args, **kwargs)
@classmethod
def update_external_id(cls, instance_id, external_id):
"""更新外部ID的静态方法"""
cls.objects.filter(id=instance_id).update(external_id=external_id)
class Meta:
indexes = [
models.Index(fields=['type']),
models.Index(fields=['department']),
models.Index(fields=['group'])
]
def __str__(self):
return f"{self.name} ({self.get_type_display()})"
def clean(self):
"""验证知识库类型与创建者权限是否匹配"""
try:
user = User.objects.get(id=self.user_id)
if user.role == 'member' and self.type != 'private':
raise ValidationError('组员只能创建私人知识库')
if user.role == 'leader' and self.type not in ['member', 'private']:
raise ValidationError('组长只能创建成员级或私人知识库')
except User.DoesNotExist:
raise ValidationError('创建者不存在')
def to_response_dict(self):
"""转换为API响应格式"""
return {
"create_time": self.create_time.isoformat(),
"update_time": self.update_time.isoformat(),
"id": str(self.id),
"name": self.name,
"desc": self.desc,
"type": self.type,
"user_id": str(self.user_id),
"char_length": self.char_length,
"document_count": self.document_count
}
def to_external_format(self):
"""转换为外部接口格式"""
return {
"name": self.name,
"desc": self.desc,
"documents": self.documents
}
class KnowledgeBaseDocument(models.Model):
"""知识库文档关联模型"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
knowledge_base = models.ForeignKey(
KnowledgeBase,
on_delete=models.CASCADE,
related_name='kb_documents',
verbose_name='知识库'
)
document_id = models.CharField(max_length=100, verbose_name='文档ID')
document_name = models.CharField(max_length=255, verbose_name='文档名称')
external_id = models.CharField(max_length=100, verbose_name='外部文档ID')
uploader_name = models.CharField(max_length=100, default="未知用户", verbose_name='上传者姓名')
status = models.CharField(
max_length=20,
default='active',
choices=[
('active', '有效'),
('deleted', '已删除')
],
verbose_name='状态'
)
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
unique_together = ['knowledge_base', 'document_id']
indexes = [
models.Index(fields=['knowledge_base', 'status']),
models.Index(fields=['document_id']),
models.Index(fields=['external_id'])
]
verbose_name = '知识库文档'
verbose_name_plural = '知识库文档'
def __str__(self):
return f"{self.knowledge_base.name} - {self.document_name}"