Django DRF API 编写规范(程序设计规则)
为了确保 Django DRF 代码的可维护性、可扩展性和高质量,API 设计不仅要符合 RESTful 规范,还需要遵循一定的程序设计规则。以下是一些关键的编写规范,以保证代码的清晰性、可读性和稳定性。
一、代码组织与结构
(一)项目目录结构
建议遵循 Django 的最佳实践,将 API 代码模块化,保持清晰的层次结构:
my_project/
│── my_app/
│ │── models.py # 数据模型
│ │── serializers.py # 序列化器
│ │── views.py # 视图
│ │── urls.py # 路由
│ │── permissions.py # 权限
│ │── paginations.py # 分页
│ │── filters.py # 过滤器
│ │── services.py # 业务逻辑
│ └── tests/ # 单元测试
│── config/
│ │── settings.py # 项目配置
│ │── urls.py # 主路由
│── manage.py
models.py
:定义数据库模型serializers.py
:定义数据序列化逻辑views.py
:编写 API 逻辑permissions.py
:自定义权限paginations.py
:自定义分页逻辑filters.py
:定义过滤器services.py
:封装业务逻辑,避免视图代码膨胀tests/
:单元测试,提高代码质量
二、视图层规范
(一)优先使用 ViewSet
避免 APIView
,尽可能使用 ModelViewSet
来减少代码重复:
from rest_framework.viewsets import ModelViewSet
from .models import User
from .serializers import UserSerializerclass UserViewSet(ModelViewSet):queryset = User.objects.all()serializer_class = UserSerializer
如果 ViewSet
过重,可以拆分逻辑到 services.py
,避免过多业务逻辑混杂在视图层。
(二)限制 ViewSet
的 HTTP 方法
如果某个 ViewSet
只需要支持部分 HTTP 方法,应在 viewset
里限制:
class UserViewSet(ModelViewSet):queryset = User.objects.all()serializer_class = UserSerializerhttp_method_names = ['get', 'post', 'patch', 'delete']
三、序列化器(Serializers)规范
(一)使用 ModelSerializer
尽可能使用 ModelSerializer
,减少重复代码:
from rest_framework import serializers
from .models import Userclass UserSerializer(serializers.ModelSerializer):class Meta:model = Userfields = ["id", "username", "email", "created_at"]
(二)避免 serializers.Serializer
直接定义字段
除非是特殊业务数据结构,否则不推荐手写字段:
# ❌ 不推荐
class CustomSerializer(serializers.Serializer):username = serializers.CharField()email = serializers.EmailField()
尽量使用 ModelSerializer
直接绑定模型,减少维护成本。
(三)字段验证逻辑放在 validate_xxx
class UserSerializer(serializers.ModelSerializer):class Meta:model = Userfields = ["id", "username", "email"]def validate_email(self, value):if "spam" in value:raise serializers.ValidationError("Email contains spam content")return value
四、业务逻辑拆分(Services 层)
为了避免 views.py
代码过于庞大,建议将业务逻辑封装到 services.py
:
# services.py
def create_user(username, email):if User.objects.filter(email=email).exists():raise ValueError("Email already exists")return User.objects.create(username=username, email=email)
然后在 views.py
里调用:
from .services import create_userclass UserViewSet(ModelViewSet):...def perform_create(self, serializer):create_user(serializer.validated_data["username"], serializer.validated_data["email"])
五、权限控制(Permissions)
(一)尽可能使用 permissions.py
单独管理权限
避免直接在 views.py
里写权限判断,而是使用 Django DRF 的 permissions
机制:
from rest_framework.permissions import BasePermissionclass IsAdminUserOrReadOnly(BasePermission):def has_permission(self, request, view):if request.method in ['GET']:return Truereturn request.user and request.user.is_staff
然后在 views.py
里使用:
class UserViewSet(ModelViewSet):permission_classes = [IsAdminUserOrReadOnly]
六、查询优化
(一)使用 select_related
和 prefetch_related
避免 N+1 查询:
class UserViewSet(ModelViewSet):queryset = User.objects.select_related("profile").all()
(二)使用分页减少数据库压力
配置全局分页:
REST_FRAMEWORK = {'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination','PAGE_SIZE': 10
}
七、异常处理
(一)全局异常处理
在 exception_handler.py
里统一管理异常:
from rest_framework.views import exception_handlerdef custom_exception_handler(exc, context):response = exception_handler(exc, context)if response is not None:response.data = {"code": response.status_code,"message": response.data.get("detail", "An error occurred")}return response
在 settings.py
里配置:
REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'my_app.exception_handler.custom_exception_handler'
}
八、单元测试(Tests)
(一)测试 API 逻辑
编写 pytest
测试,确保 API 可用:
import pytest
from rest_framework.test import APIClient@pytest.mark.django_db
def test_create_user():client = APIClient()response = client.post("/api/users/", {"username": "john", "email": "john@example.com"})assert response.status_code == 201
(二)覆盖率标准
使用 pytest
运行测试,并确保代码覆盖率:
pytest --cov=my_app
总结
- 遵循 Django 项目目录结构,保持模块化设计。
- 使用
ViewSet
处理 API 逻辑,并限制 HTTP 方法。 - 优先使用
ModelSerializer
,避免重复字段定义。 - 业务逻辑拆分到
services.py
,避免views.py
代码过重。 - 权限控制统一放在
permissions.py
,避免手写权限逻辑。 - 使用
select_related
和prefetch_related
进行查询优化。 - 使用
custom_exception_handler
统一异常处理。 - 编写
pytest
单元测试,确保代码稳定。
通过这些规则,可以提升 Django DRF API 的可维护性、扩展性和高效性,使代码更加清晰易读。