【后端】【django drf】Django DRF API 编写规范(程序设计规则)

devtools/2025/3/17 16:39:19/

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 UserSerializerclass 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 = UserSerializerhttp_method_names = ['get', 'post', 'patch', 'delete']

三、序列化器(Serializers)规范

(一)使用 ModelSerializer

尽可能使用 ModelSerializer,减少重复代码:

python">from rest_framework import serializers
from .models import Userclass UserSerializer(serializers.ModelSerializer):class Meta:model = Userfields = ["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 = 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

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_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 机制:

python">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 里使用:

python">class UserViewSet(ModelViewSet):permission_classes = [IsAdminUserOrReadOnly]

六、查询优化

(一)使用 select_relatedprefetch_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_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 里配置:

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": "john@example.com"})assert response.status_code == 201

(二)覆盖率标准

使用 pytest 运行测试,并确保代码覆盖率:

pytest --cov=my_app

总结

  1. 遵循 Django 项目目录结构,保持模块化设计
  2. 使用 ViewSet 处理 API 逻辑,并限制 HTTP 方法
  3. 优先使用 ModelSerializer,避免重复字段定义
  4. 业务逻辑拆分到 services.py,避免 views.py 代码过重
  5. 权限控制统一放在 permissions.py,避免手写权限逻辑
  6. 使用 select_relatedprefetch_related 进行查询优化
  7. 使用 custom_exception_handler 统一异常处理
  8. 编写 pytest 单元测试,确保代码稳定

通过这些规则,可以提升 Django DRF API 的可维护性、扩展性和高效性,使代码更加清晰易读。


http://www.ppmy.cn/devtools/167870.html

相关文章

DeepSeek R1 与 ktransformers:结合苹果 M4 Mac 的 LLM 推理深度分析

引言 大型语言模型(LLM)的快速发展为人工智能领域带来了革命性变化。DeepSeek R1 和 ktransformers 代表了软件层面的最新突破,而苹果在 2025 年 3 月 12 日发布的 M4 Mac 系列则提供了硬件支持。本文将深入分析这些技术的交汇点&#xff0c…

Git版本控制系统详解

文章目录 一、Git简介二、Git的基本原理三、Git的安装与配置安装配置 四、Git常用指令详解1. git init2. git clone3. git add4. git commit5. git status6. git diff7. git log8. git branch9. git checkout10. git merge11. git pull12. git push 五、Git的进阶用法1. 远程仓…

animes 和 css对比

Anime.js 并不是纯粹的 CSS 动画库,而是一个基于 JavaScript 的动画库。它可以通过操作 DOM 元素的属性(如 style、transform、opacity 等)来实现动画效果。虽然 Anime.js 的某些功能与 CSS 动画类似,但它的工作原理和功能范围与 …

HTTPS 证书相关

通常涉及到政府机构或官方组织的网站,这类网站对安全性和可信度要求较高,因此在选择 HTTPS 证书时需要特别注意。以下是适合的证书类型: 1. OV(Organization Validation)证书 适用场景:适用于需要验证组织…

设备管理VTY(Telnet、SSH)

实验目的:物理机远程VTY通过telnet协议登录AR1,ssh协议登录AR2和sw 注意配置Cloud1: 注意!!博主的物理机VMnet8--IP:192.168.160.1,所以AR1路由0/0/0端口才添加IP:192.168.160.3,每个…

Spring Boot + Vue 基于RSA+AES的混合加密

目录 一、后端实现 二、前端实现(Vue2) 三、补充 1.增强安全措施 四、最后说明 步骤大致如下: 后端生成RSA密钥对,提供公钥接口。前端请求公钥,生成随机AES密钥和IV。用RSA公钥加密AES密钥,用AES密钥加密…

【ES6】03-Set + Map

本文介绍两种集合 set map 的操作和方法。 目录 1. Set 1.1 set基本使用 1.2 add 1.3 delete 1.4 has 1.5 size 1.6 set转换为数组 1.7 拓展运算符 1.8 for...of 1.9 forEach 1.10 set给数组去重 2. Map 2.1 创建map集合 2.2 set添加元素 2.3 delete删除元素 …

奇安信二面

《网安面试指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39…