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
来减少代码重复:
python
from rest_framework.viewsets import ModelViewSet
from .models import User
from .serializers import UserSerializer
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
如果 ViewSet
过重,可以拆分逻辑到 services.py
,避免过多业务逻辑混杂在视图层。
(二)限制 ViewSet
的 HTTP 方法
如果某个 ViewSet
只需要支持部分 HTTP 方法,应在 viewset
里限制:
python
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
http_method_names = ['get', 'post', 'patch', 'delete']
三、序列化器(Serializers)规范
(一)使用 ModelSerializer
尽可能使用 ModelSerializer
,减少重复代码:
python
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ["id", "username", "email", "created_at"]
(二)避免 serializers.Serializer
直接定义字段
除非是特殊业务数据结构,否则不推荐手写字段:
python
# ❌ 不推荐
class CustomSerializer(serializers.Serializer):
username = serializers.CharField()
email = serializers.EmailField()
尽量使用 ModelSerializer
直接绑定模型,减少维护成本。
(三)字段验证逻辑放在 validate_xxx
python
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ["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
:
python
# 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
里调用:
python
from .services import create_user
class 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
机制:
python
from rest_framework.permissions import BasePermission
class IsAdminUserOrReadOnly(BasePermission):
def has_permission(self, request, view):
if request.method in ['GET']:
return True
return request.user and request.user.is_staff
然后在 views.py
里使用:
python
class UserViewSet(ModelViewSet):
permission_classes = [IsAdminUserOrReadOnly]
六、查询优化
(一)使用 select_related
和 prefetch_related
避免 N+1 查询:
python
class UserViewSet(ModelViewSet):
queryset = User.objects.select_related("profile").all()
(二)使用分页减少数据库压力
配置全局分页:
python
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
七、异常处理
(一)全局异常处理
在 exception_handler.py
里统一管理异常:
python
from rest_framework.views import exception_handler
def 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
里配置:
python
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_app.exception_handler.custom_exception_handler'
}
八、单元测试(Tests)
(一)测试 API 逻辑
编写 pytest
测试,确保 API 可用:
python
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": "[email protected]"})
assert response.status_code == 201
(二)覆盖率标准
使用 pytest
运行测试,并确保代码覆盖率:
bash
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 的可维护性、扩展性和高效性,使代码更加清晰易读。