doccano后端开发:Django REST框架API扩展实战
【免费下载链接】doccano 项目地址: https://gitcode.com/gh_mirrors/doc/doccano
项目架构概览
doccano后端基于Django REST框架构建,采用模块化设计理念,将不同功能划分为独立的Django应用。核心API架构遵循RESTful设计原则,通过ViewSet和APIView实现资源的CRUD操作。
主要后端模块结构如下:
- API层:backend/api/ - 包含基础API实现,如任务状态检查
- 业务模块:backend/projects/, backend/examples/, backend/labels/等
- 配置文件:backend/config/ - Django项目配置
- 工具脚本:tools/ - 包含部署和维护脚本
核心API实现模式
1. 基础视图实现
doccano后端主要使用两种视图模式:generics.ListCreateAPIView用于资源列表和创建,APIView用于自定义复杂逻辑。
示例代码:examples/views/example.py
class ExampleList(generics.ListCreateAPIView):
serializer_class = ExampleSerializer
permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)]
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
ordering_fields = ("created_at", "updated_at", "score")
search_fields = ("text", "filename")
model = Example
filterset_class = ExampleFilter
@property
def project(self):
return get_object_or_404(Project, pk=self.kwargs["project_id"])
def get_queryset(self):
member = get_object_or_404(Member, project=self.project, user=self.request.user)
if member.is_admin():
return self.model.objects.filter(project=self.project)
# 普通成员只能访问分配给自己的示例
queryset = self.model.objects.filter(project=self.project, assignments__assignee=self.request.user)
if self.project.random_order:
queryset = queryset.order_by("assignments__id")
return queryset
2. URL路由配置
URL路由采用集中式管理,通过urls.py文件定义API端点与视图的映射关系。
示例代码:backend/api/urls.py
from django.urls import path
from .views import TaskStatus
urlpatterns = [
path(route="tasks/status/<task_id>", view=TaskStatus.as_view(), name="task_status"),
]
3. 权限控制机制
权限系统基于Django REST框架的权限类实现,结合项目角色管理细粒度访问控制。
权限类组合示例:
permission_classes = [IsAuthenticated & (IsProjectAdmin | IsProjectStaffAndReadOnly)]
其中IsProjectAdmin和IsProjectStaffAndReadOnly定义在projects/permissions.py中,实现了基于项目角色的权限检查。
实战:扩展自定义API端点
步骤1:创建视图类
假设我们需要添加一个批量分配示例的API端点,可以创建如下视图:
# File: backend/examples/views/assignment.py
class BulkAssignment(APIView):
serializer_class = AssignmentSerializer
permission_classes = [IsAuthenticated & IsProjectAdmin]
def post(self, *args, **kwargs):
try:
strategy_name = StrategyName[self.request.data["strategy_name"]]
except KeyError:
return Response(
{"detail": "Invalid strategy name"},
status=status.HTTP_400_BAD_REQUEST,
)
# 实现批量分配逻辑
bulk_assign(
project_id=self.kwargs["project_id"],
strategy_name=strategy_name,
member_ids=workload_allocation.member_ids,
weights=workload_allocation.weights,
)
return Response(status=status.HTTP_201_CREATED)
步骤2:配置URL路由
在应用的urls.py中添加新端点:
# File: backend/examples/urls.py
from django.urls import path
from .views.assignment import BulkAssignment
urlpatterns = [
# 其他URL配置...
path('projects/<int:project_id>/assignments/bulk/', BulkAssignment.as_view(), name='bulk-assignment'),
]
步骤3:实现业务逻辑
将核心业务逻辑封装在专门的用例模块中,保持视图层简洁:
# File: backend/examples/assignment/usecase.py
def bulk_assign(project_id, strategy_name, member_ids, weights):
"""
批量分配示例给项目成员
"""
project = get_object_or_404(Project, pk=project_id)
members = Member.objects.filter(id__in=member_ids, project=project)
# 根据选择的策略分配示例
strategy = get_strategy(strategy_name)
assignments = strategy.assign(project.examples.all(), members, weights)
Assignment.objects.bulk_create(assignments)
return assignments
测试与调试
API端点测试
使用Django REST框架自带的测试工具进行API测试:
# File: backend/examples/tests/test_api.py
from rest_framework.test import APITestCase
from rest_framework import status
from django.urls import reverse
class ExampleAPITest(APITestCase):
def setUp(self):
# 创建测试用户、项目和示例数据
self.user = User.objects.create_user(username='test', password='testpass')
self.client.login(username='test', password='testpass')
self.project = Project.objects.create(name='Test Project', owner=self.user)
def test_list_examples(self):
url = reverse('example-list', kwargs={'project_id': self.project.id})
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
权限测试
验证不同角色用户对API的访问权限:
def test_assignment_permissions(self):
# 测试非管理员用户不能执行批量分配
non_admin_user = User.objects.create_user(username='nonadmin', password='pass')
Member.objects.create(user=non_admin_user, project=self.project, role='annotator')
self.client.login(username='nonadmin', password='pass')
url = reverse('bulk-assignment', kwargs={'project_id': self.project.id})
response = self.client.post(url, {'strategy_name': 'ROUND_ROBIN', 'workloads': []})
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
部署与扩展
配置生产环境
生产环境部署使用Docker Compose,配置文件位于docker/docker-compose.prod.yml,采用三层架构:
- Nginx作为反向代理
- Django应用服务器
- Celery处理异步任务
性能优化建议
1.** 数据库优化 :为频繁查询的字段添加索引,如示例表的project_id和assignments字段 2. 缓存策略 :使用Redis缓存常用数据,如项目配置和标签定义 3. 异步处理 **:将耗时操作(如数据导入导出)通过Celery异步执行,实现代码位于backend/data_import/celery_tasks.py和backend/data_export/celery_tasks.py
总结与扩展阅读
通过本文介绍的方法,你可以基于Django REST框架扩展doccano的API功能。关键要点包括:
- 遵循项目现有模块化结构
- 使用Django REST框架的通用视图和权限类
- 将业务逻辑与视图分离,保持代码清晰
- 添加完善的测试用例确保API可靠性
深入学习可参考以下资源:
- 官方开发指南:docs/developer_guide.md
- Django REST框架文档:https://www.django-rest-framework.org/
- 项目API实现示例:backend/labels/views.py、backend/projects/views/
【免费下载链接】doccano 项目地址: https://gitcode.com/gh_mirrors/doc/doccano
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




