一、环境搭建:Docker容器化部署
为了保证开发环境的一致性,本教程采用Docker Compose进行一键式环境编排。我们将构建一个包含Python后端、PostgreSQL数据库和Nginx反向代理的完整运行环境。
在项目根目录下创建docker-compose.yml文件。请直接复制以下配置,不要遗漏任何依赖项:
```
version: '3.8'
services:
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: archive_db
POSTGRES_USER: archive_user
POSTGRES_PASSWORD: secure_password_123
ports:
- "5432:5432"
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
- static_volume:/code/staticfiles
- media_volume:/code/media
ports:
- "8000:8000"
depends_on:
- db
environment:
- DATABASE_URL=postgres://archive_user:secure_password_123@db:5432/archive_db
volumes:
postgres_data:
static_volume:
media_volume:
```
接着,在同级目录下创建Dockerfile用于定义后端服务的构建规则:
```
FROM python:3.9
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
RUN python manage.py collectstatic --noinput
```
创建requirements.txt,明确指定版本号以防止依赖冲突:
```
Django==4.2.5
djangorestframework==3.14.0
django-cors-headers==4.3.0
psycopg2-binary==2.9.7
Pillow==10.0.1
python-decouple==3.8
```
执行以下命令启动环境。这是启动所有服务的唯一入口命令:
docker-compose up --build
二、后端开发:Django核心业务逻辑
环境启动后,我们需要构建后端API。这里我们使用Django REST Framework来快速实现档案的增删改查。进入容器生成项目骨架:
docker-compose exec web django-admin startproject core .
docker-compose exec web python manage.py startapp archives
1. 数据库模型设计
编辑archives/models.py,设计档案的核心字段。这里包含文件存储、分类和元数据管理:
```
from django.db import models
from django.contrib.auth.models import User
class ArchiveCategory(models.Model):
name = models.CharField(max_length=100, unique=True, verbose_name="分类名称")
description = models.TextField(blank=True, verbose_name="分类描述")
class Meta:
verbose_name = "档案分类"
verbose_name_plural = verbose_name
class ArchiveDocument(models.Model):
STATUS_CHOICES = [
('draft', '草稿'),
('active', '归档'),
('archived', '封存'),
]
title = models.CharField(max_length=200, verbose_name="档案标题")
file = models.FileField(upload_to='documents/%Y/%m/%d/', verbose_name="档案文件")
category = models.ForeignKey(ArchiveCategory, on_delete=models.PROTECT, verbose_name="所属分类")
uploader = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="上传人")
uploaded_at = models.DateTimeField(auto_now_add=True, verbose_name="上传时间")
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft', verbose_name="状态")
tags = models.CharField(max_length=255, blank=True, help_text="使用逗号分隔", verbose_name="标签")
class Meta:
verbose_name = "档案文档"
verbose_name_plural = verbose_name
ordering = ['-uploaded_at']
def __str__(self):
return self.title
```
模型创建完成后,必须执行数据库迁移命令使表结构生效:
docker-compose exec web python manage.py makemigrations
docker-compose exec web python manage.py migrate
2. 文件上传与接口实现

编辑archives/views.py,编写处理文件上传和列表展示的逻辑。这里我们使用APIView来获得更细粒度的控制:
```
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.parsers import MultiPartParser, FormParser
from .models import ArchiveDocument, ArchiveCategory
from .serializers import ArchiveDocumentSerializer
class FileUploadView(APIView):
parser_classes = (MultiPartParser, FormParser)
def post(self, request, args, kwargs):
file_serializer = ArchiveDocumentSerializer(data=request.data)
if file_serializer.is_valid():
自动关联当前上传用户(实际项目中需从JWT Token获取)
file_serializer.validated_data['uploader'] = request.user
file_serializer.save()
return Response(file_serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def get(self, request, args, kwargs):
documents = ArchiveDocument.objects.all()
支持按分类筛选
category_id = request.query_params.get('category')
if category_id:
documents = documents.filter(category_id=category_id)
serializer = ArchiveDocumentSerializer(documents, many=True)
return Response(serializer.data)
```
创建archives/serializers.py来序列化数据:
```
from rest_framework import serializers
from .models import ArchiveDocument
class ArchiveDocumentSerializer(serializers.ModelSerializer):
uploader_name = serializers.ReadOnlyField(source='uploader.username')
class Meta:
model = ArchiveDocument
fields = ['id', 'title', 'file', 'category', 'uploader_name', 'uploaded_at', 'status', 'tags']
```
在core/urls.py中注册路由:
```
from django.urls import path
from archives.views import FileUploadView
urlpatterns = [
path('api/documents/', FileUploadView.as_view(), name='file-upload'),
]
```
三、前端开发:Vue3交互界面
为了实现现代化的交互体验,我们使用Vue3配合Axios进行前端开发。在项目根目录创建frontend目录,并初始化:
npm init vue@latest frontend
cd frontend && npm install axios
在frontend/src/components下创建FileUpload.vue组件。这是用户操作的核心入口,必须包含完整的文件选择和进度反馈逻辑:
```
档案上传录入
{{ uploadStatus }}
```
四、案例实操:分级权限管理落地
在实际企业培训场景中,档案管理最核心的痛点是“谁能看什么”。本章节演示如何基于Django的Guardian库实现对象级别的权限控制。假设场景:人事部只能查看人事档案,技术部只能查看技术文档。
安装依赖:
pip install django-guardian
修改core/settings.py,注册应用和权限后端:
```
INSTALLED_APPS = [
...
'guardian',
]
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'guardian.backends.ObjectPermissionBackend',
)
```
更新archives/views.py,增加权限校验逻辑。这是确保数据安全的关键代码:
```
from guardian.shortcuts import assign_perm, get_objects_for_user
class SecureDocumentView(APIView):
def get(self, request):
核心逻辑:仅获取用户有查看权限的文档对象
假设我们在上传时分配了 'archives.view_archivedocument' 权限
user_docs = get_objects_for_user(request.user, 'archives.view_archivedocument', klass=ArchiveDocument)
同时也要包含用户自己上传的文件
own_docs = ArchiveDocument.objects.filter(uploader=request.user)
合并查询集并去重
all_allowed_docs = user_docs.union(own_docs)
serializer = ArchiveDocumentSerializer(all_allowed_docs, many=True)
return Response(serializer.data)
def post(self, request):
... 上传逻辑同上 ...
上传成功后,自动分配给用户所在部门的所有成员查看权限
new_doc = file_serializer.save()
假设用户有 department 属性
user_dept = request.user.department
if user_dept:
获取同部门的所有用户
colleagues = User.objects.filter(department=user_dept)
for colleague in colleagues:
assign_perm('view_archivedocument', colleague, new_doc)
return Response({"message": "上传并授权完成"}, status=201)
```
为了测试此功能,我们需要在Django Shell中模拟创建用户和分配权限的脚本。这是培训中常用的验证步骤:
```
进入容器 shell
docker-compose exec web python manage.py shell
执行以下Python代码
from django.contrib.auth.models import User
from archives.models import ArchiveDocument, ArchiveCategory
from guardian.shortcuts import assign_perm
1. 创建测试用户
hr_user = User.objects.create_user('hr_manager', 'hr@company.com', 'password123')
it_user = User.objects.create_user('it_staff', 'it@company.com', 'password123')
2. 创建分类
hr_cat = ArchiveCategory.objects.create(name="人事档案")
it_cat = ArchiveCategory.objects.create(name="技术文档")
3. 模拟上传一个人事档案
doc = ArchiveDocument.objects.create(
title="员工入职登记表.pdf",
category=hr_cat,
uploader=hr_user,
status='active'
)
4. 关键操作:给人事用户分配查看该文档的权限
assign_perm('archives.view_archivedocument', hr_user, doc)
5. 验证:检查it_user是否有权限(应返回False)
print(it_user.has_perm('archives.view_archivedocument', doc))
```
通过以上步骤,你已经构建了一个具备基础权限隔离能力的档案管理系统原型。在实际落地培训中,应重点强调assign_perm调用时机以及get_objects_for_user在列表查询中的使用,这是防止越权访问的最后一道防线。