背景:很多人写 Django 时容易“什么都往 views 里塞”,结果项目一大就乱套了。

需要把 视图层 / 业务层 / 数据层 等职责清晰分出来。
在这里插入图片描述

图解说明

  • Client:浏览器 / App / 前端调用 API。

  • urls.py:定义 API 路由,把请求分发到对应的 ViewSet。

  • views.py:控制器层(类似 Spring Controller),只负责调度。

  • serializers.py:数据输入/输出格式化 & 校验(类似 DTO/Validator)。

  • services.py:业务逻辑核心(类似 Service)。

  • models.py:数据库 ORM(类似 Repository/DAO)。

  • tasks.py:异步任务(Celery/RQ 等),做发邮件/推送等耗时操作。

  • permissions.py:权限认证、用户访问控制。

  • utils.py:通用工具函数。

  • Database:最终的数据存储。

下面是详细的介绍


一、Django 的天然 MVC / MTV 结构

Django 官方称之为 MTV 模式,其实和 Spring MVC 的思想一致,只是命名不同:

  • Model(模型) → 数据层

    • 定义数据库表(ORM)
    • 封装业务数据对象
    • 数据校验(字段约束)
  • Template(模板) → 表现层

    • 前端渲染 HTML 的模板(如果是纯 API 项目,模板层弱化)
  • View(视图) → 控制层

    • 接收请求、调用业务逻辑、返回响应(JSON/HTML)

不过在实际开发中,Django 的 View 很容易变肥,所以我们需要借鉴 Spring MVC 的 Service/Controller 分层思想,进行更合理的拆分。


二、推荐的 Django 分层逻辑

1. models.py(数据模型层)

  • 定义数据库结构(ORM)
  • 约束字段规则(null、unique、default 等)
  • 封装一些跟数据紧密相关的方法(例如 User.objects.active_users()

👉 注意:不要在 model 里写复杂的业务逻辑,它应该只管数据。


2. serializers.py(数据序列化 & 校验层)

  • 类似 Spring 里的 DTO + Validator

  • 负责:

    • 数据的输入/输出转换(JSON ↔ Python 对象)
    • 字段级/对象级校验
    • 定义 API 数据格式

👉 业务逻辑不要放这里,它只管“数据是否合法、怎么展示”。


3. views.py / api.py(控制器层)

  • 类似 Spring 的 Controller

  • 负责:

    • 接收 HTTP 请求
    • 调用 Service 层 处理逻辑
    • 返回响应(Response/JsonResponse)

👉 只做 调度,不做业务。保持尽量轻量。


4. services.py(业务逻辑层,推荐新增)

  • 类似 Spring 的 Service

  • 封装核心业务逻辑,便于复用和单元测试

  • 例如:

    class OrderService:@staticmethoddef create_order(user, items):# 校验库存# 扣减余额# 创建订单# 触发通知return order
    

👉 最重要的层,能避免 “胖 View” 问题。


5. tasks.py(异步任务层)

  • 放 Celery/RQ/定时任务逻辑
  • 例如发送邮件、推送通知、批量清理数据

👉 让耗时操作异步化,保持 API 快速响应。


6. urls.py(路由层)

  • 定义 API 路由,类似 Spring 的 @RequestMapping
  • 逻辑不要写在这里。

7. permissions.py / authentication.py

  • 类似 Spring 的拦截器/过滤器
  • 处理权限校验、用户认证

8. utils.py / helpers.py

  • 存放通用工具函数(时间处理、加密、日志等)
  • 避免重复造轮子

      • 案例

Django REST framework (DRF) 做一个实际案例「订单系统」


一、案例背景

我们做一个最简单的订单系统 API:

  • 用户下单
  • 查询订单
  • 支付订单

涉及到的对象:UserOrder
涉及到的逻辑:下单支付


二、推荐目录结构

项目叫 shop,应用叫 orders

shop/
│
├── shop/
│   ├── settings.py
│   ├── urls.py
│   ├── wsgi.py
│   └── asgi.py
│
├── apps/
│   └── orders/
│       ├── models.py         # 数据模型 (ORM)
│       ├── serializers.py    # 序列化 & 校验
│       ├── views.py          # 控制器 (调度层)
│       ├── services.py       # 业务逻辑层
│       ├── tasks.py          # 异步任务 (如发邮件)
│       ├── permissions.py    # 权限控制
│       ├── urls.py           # 路由定义
│       └── utils.py          # 工具方法
│
├── requirements.txt
└── manage.py

Spring MVC 对比

  • Controllerviews.py
  • Serviceservices.py
  • Repository/DAOmodels.py
  • DTO/VOserializers.py
  • Filter/Interceptorpermissions.pymiddleware

三、代码示例(精简版)

1. models.py(数据模型)

from django.db import models
from django.contrib.auth.models import Userclass Order(models.Model):user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="orders")product_name = models.CharField(max_length=100)price = models.DecimalField(max_digits=10, decimal_places=2)is_paid = models.BooleanField(default=False)created_at = models.DateTimeField(auto_now_add=True)def __str__(self):return f"Order({self.product_name}, {self.user.username})"

2. serializers.py(数据序列化 & 校验)

from rest_framework import serializers
from .models import Orderclass OrderSerializer(serializers.ModelSerializer):class Meta:model = Orderfields = ["id", "product_name", "price", "is_paid", "created_at"]read_only_fields = ["id", "is_paid", "created_at"]

3. services.py(业务逻辑层)

from .models import Orderclass OrderService:@staticmethoddef create_order(user, product_name, price):return Order.objects.create(user=user, product_name=product_name, price=price)@staticmethoddef pay_order(order: Order):if order.is_paid:raise ValueError("订单已支付")order.is_paid = Trueorder.save()return order

👉 优点:

  • views 变得很轻,只做调度
  • 业务逻辑放在 services.py,可复用、可测试

4. views.py(控制器层)

from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action
from .models import Order
from .serializers import OrderSerializer
from .services import OrderServiceclass OrderViewSet(viewsets.ModelViewSet):queryset = Order.objects.all()serializer_class = OrderSerializerdef perform_create(self, serializer):# 下单逻辑交给 servicereturn OrderService.create_order(user=self.request.user,product_name=serializer.validated_data["product_name"],price=serializer.validated_data["price"],)@action(detail=True, methods=["post"])def pay(self, request, pk=None):order = self.get_object()try:order = OrderService.pay_order(order)return Response(OrderSerializer(order).data, status=status.HTTP_200_OK)except ValueError as e:return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

5. urls.py(路由层)

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import OrderViewSetrouter = DefaultRouter()
router.register(r"orders", OrderViewSet, basename="order")urlpatterns = [path("", include(router.urls)),
]

四、请求示例

  1. 创建订单
POST /orders/
{"product_name": "iPhone 16","price": "8999.00"
}
  1. 查询订单
GET /orders/
  1. 支付订单
POST /orders/1/pay/

五、为什么这是一个优秀的架构?

分层清晰

  • views:只负责 HTTP 请求和响应
  • services:封装业务逻辑,可测试,可复用
  • serializers:只做数据验证 & 转换
  • models:只管数据库

职责单一:每个文件只做一件事,方便维护。

可扩展

  • 想加支付网关?只改 services.py
  • 想做异步发邮件?写在 tasks.py,不影响 views.py

团队协作友好

  • 前端/后端都清楚 API 长啥样
  • 后端开发知道逻辑放哪里,不会出现“胖 views”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96219.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96219.shtml
英文地址,请注明出处:http://en.pswp.cn/web/96219.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL】从零开始了解数据库开发 --- 表的操作

永远记住,你的存在是有意义的, 你很重要, 你是被爱着的, 而且你为这个世界带来了无可取代的东西。 -- 麦克西 《男孩、鼹鼠、狐狸和马》-- 从零开始了解数据库开发创建数据表查看表结构修改数据表结构重命名表复制表删除表今天我们…

MySQL底层架构设计原理详细介绍

文章目录一、MySQL体系结构概览二、连接层(Connection Layer)1. 连接器(Connectors)2. 连接池(Conncction Pool)三、服务层(Server Layer)1. SQL接口组件(SQL Interface&…

QB/T 4674-2021 汽车内装饰用聚氨酯束状超细纤维合成革检测

汽车内饰品聚氨酯束状超细纤维合成革是指以海岛型双组份或多组分纤维加工成飞织造布,再经水性聚氨酯树脂或溶剂型聚氨酯树脂浸渍、湿法凝固、溶剂或碱液萃取及后整理等工艺制成的汽车内装饰皮革。QB/T 4674-2021 汽车内装饰用聚氨酯束状超细纤维合成革检测项目测试项…

QML和Qt Quick

QML和Qt Quick QML 和 Qt Quick 是 Qt 框架中紧密相关但概念不同的两个部分,它们之间的关系可以用如下方式清晰说明: 核心区别概览​​特性​​​​QML​​​​Qt Quick​​​​本质​​声明式编程​​语言​​基于 QML 的​​框架/库​​​​作用​​定…

JavaScript 结构型设计模式详解

1. 代理模式1.1. 使用场景代理模式在不改变原始对象的前提下,通过代理对象控制对其访问,通常用于权限控制、延迟加载、远程调用等场景。在前端开发中,可以通过代理模式对网络请求、缓存机制等进行控制。1.2. 代码实现class ApiService {reque…

摄像头模块在运动相机中的特殊应用

运动相机作为记录高速运动场景的专用设备,其摄像头模块的设计与普通消费电子产品存在显著差异。根据行业资料和技术发展,摄像头模块在运动相机中的特殊应用主要体现在以下五个维度:一、极端环境适应性设计运动相机的摄像头模块针对户外运动场…

SpringBoot + MinIO/S3 文件服务实现:FileService 接口与 FileServiceImpl 详解

在企业项目中,文件上传和管理是非常常见的需求。本文基于 芋道源码 的实现,介绍如何封装一个通用的 文件服务 FileService,支持:文件上传(保存数据库记录 存储文件到 S3/MinIO 等对象存储)文件下载与删除文…

Oracle RAC认证矩阵:规避风险的关键指南

RAC Certification Matrix(RAC认证矩阵) 是Oracle官方发布的硬件、软件与操作系统兼容性清单,明确规定了哪些平台、组件和版本可以正式支持Oracle RAC(Real Application Clusters)的部署。它是搭建或升级RAC环境时必须…

【自然语言处理与大模型】如何通过微调来agent性能?

虽然大模型本身具备一定的指令理解和工具调用潜力,但在实际应用中,尤其是在复杂或专业领域,往往需要通过微调来提升Agent的工具调用能力。问题一:基座模型无法准确识别或选择特定领域的工具当Agent需要在医疗、金融、法律、工业控…

在 Keil 中将 STM32 工程下载到 RAM 进行调试运行

在 Keil 中将 STM32 工程下载到 RAM 进行调试运行 在使用 STM32 进行调试时,默认情况下代码会被烧写到 Flash 中运行。然而,Flash 写入速度较慢,擦写次数有限,且调试过程中频繁烧写可能影响开发效率。在某些场景下(如快…

【51单片机】【protues仿真】基于51单片机宠物投食系统

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 一、主要功能 1、LCD1602液晶显示时间、温度、食物重量 2、按键手动投喂食物​ 3、称重模块检测当前食物重量 4、食物重量小于阈值会声光警报并自动投喂 二、使用步骤 基于51单片机的宠物投食…

腾讯云负载均衡增加访问策略后访问失败

为了测试,在负载均衡的安全组添加2条安全策略,限制办公室内IP可访问,其他IP地址拒绝所有访问。结果,访问失败。经过反复测试,主要是js问价加载失败,动态接口访问代码返回正常。再进行测试,发现去…

CSS的文本样式

1.文本样式的分类注意&#xff1a;必须先建立标签&#xff0c;再在head中修改1.1字体样式1.1.1字体颜色代码演示<head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&g…

R语言读取excel文件数据-解决na问题

文章目录安装R语言运行环境实现代码遇到的问题总结安装R语言运行环境 安装教程连接, 包含国内镜像快速下载 实现代码 实现思路&#xff1a;使用python将文件的空字符的位置变成0&#xff0c;生成csv文件后交给R语言处理python实现代码如下&#xff1a; import pandas as pd…

【Nginx 运维实战】版本替换:强制 vs 平滑升级全解析

【Nginx 运维实战】版本替换&#xff1a;强制 vs 平滑升级全解析一&#xff1a;版本替换的两种思路二&#xff1a;使用场景对比三&#xff1a;实战1&#xff09;强制替换1.备份旧版本2.替换为新版本3.**赋予执行权限**4.**重启 Nginx**2&#xff09;平滑替换1.确认进程文件2.备…

MQ-消息队列

定义 Mssage Queue&#xff1a;消息队列。它是一种“先进先出”&#xff08;FIFO&#xff09;的数据结构&#xff0c;用于在分布式系统或应用程序之间进行异步通信。组成1. 生产者&#xff08;Producer&#xff09;定义&#xff1a;消息的发送方&#xff0c;负责将业务系…

NVIDIA驱动程序核心的“即时编译器”(Just-in-Time, JIT Compiler)详细介绍

我们来详细、深入地剖析这个位于NVIDIA驱动程序核心的“即时编译器”&#xff08;Just-in-Time, JIT Compiler&#xff09;。它堪称CUDA生态系统成功的“幕后英雄”&#xff0c;是连接软件稳定性和硬件飞速发展的关键桥梁。 第一部分&#xff1a;JIT编译器的本质 首先&#xff…

【PS2025全网最新版】稳定版PS2025保姆级下载安装详细图文教程(附安装包)(Adobe Photoshop)

今天&#xff0c;给大家带来PS2025的保姆级下载安装图文教程。 前言&#xff1a; Adobe Photoshop 作为业界领先的图像处理与设计软件&#xff0c;持续推动着数字创意领域的发展。其应用涵盖平面设计、摄影后期、UI/UX 设计、影视特效等多个专业方向&#xff0c;为用户提供强…

分享TWS充电仓方案开发设计

TWS耳机市场“卷”到最后&#xff0c;拼的早已不只是音质&#xff0c;而是续航、交互、体积、成本四位一体。传统充电仓用多颗IC堆砌&#xff1a;升压、电量计、霍尔、LED驱动、保护IC……BOM高、贴片复杂、调试周期长。8位MCU把上述功能“一锅端”&#xff1a;单芯片即完成电源…

【Java实战㉖】深入Java单元测试:JUnit 5实战指南

目录一、单元测试概述1.1 单元测试概念1.2 单元测试优势1.3 JUnit 5 框架组成1.4 JUnit 5 环境搭建二、JUnit 5 核心功能实战2.1 测试类与测试方法2.2 测试生命周期2.3 断言方法2.4 异常测试三、单元测试进阶实战3.1 参数化测试3.2 测试套件3.3 Mockito 框架3.4 单元测试实战案…