You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复用Django业务逻辑同时支持Web视图与REST API?

最优方案:抽离业务逻辑到独立服务层

核心思路是将业务校验与核心逻辑从视图层完全剥离,封装到单独的服务模块中。无论是Django普通视图(用于Web页面交互)还是DRF的API视图/ViewSet(用于REST接口),都直接调用服务层的方法,既实现逻辑复用,又保证业务规则的一致性。

实现步骤与代码示例

1. 定义基础模型(models.py)

先明确业务相关的模型,以订单和库存为例:

from django.db import models

class Inventory(models.Model):
    area = models.CharField(max_length=50, verbose_name="区域")
    product = models.CharField(max_length=100, verbose_name="产品")
    stock_quantity = models.IntegerField(verbose_name="库存数量")

class Order(models.Model):
    order_number = models.CharField(max_length=50, unique=True, verbose_name="订单号")
    area = models.CharField(max_length=50, verbose_name="区域")
    product = models.CharField(max_length=100, verbose_name="产品")
    quantity = models.IntegerField(verbose_name="订购数量")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

2. 创建服务层(services.py)

将所有业务逻辑(比如库存校验、订单创建的原子操作)集中在这里:

from django.db import transaction
from .models import Inventory, Order
from django.core.exceptions import ValidationError

class OrderService:
    @staticmethod
    def create_order(order_data):
        """创建订单的核心逻辑:库存校验 + 订单创建 + 库存扣减(原子操作)"""
        area = order_data.get('area')
        product = order_data.get('product')
        quantity = order_data.get('quantity')

        # 校验区域内是否存在对应库存
        try:
            inventory = Inventory.objects.get(area=area, product=product)
        except Inventory.DoesNotExist:
            raise ValidationError(f"区域{area}无{product}库存")
        
        # 校验库存是否充足
        if inventory.stock_quantity < quantity:
            raise ValidationError(f"区域{area}内{product}库存不足,当前库存{inventory.stock_quantity},需订购{quantity}")
        
        # 原子事务:保证订单创建和库存扣减要么同时成功,要么同时失败
        with transaction.atomic():
            order = Order.objects.create(
                order_number=order_data.get('order_number'),
                area=area,
                product=product,
                quantity=quantity
            )
            inventory.stock_quantity -= quantity
            inventory.save()
        
        return order

3. 在Django普通视图中调用服务层(views.py)

用于Web页面的订单提交逻辑,直接复用服务层的业务规则:

from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import OrderForm
from .services import OrderService

def create_order_web(request):
    if request.method == 'POST':
        form = OrderForm(request.POST)
        if form.is_valid():
            try:
                OrderService.create_order(form.cleaned_data)
                messages.success(request, "订单创建成功")
                return redirect('order_list')
            except ValidationError as e:
                messages.error(request, str(e))
    else:
        form = OrderForm()
    return render(request, 'create_order.html', {'form': form})

4. 在DRF API视图/ViewSet中调用服务层

方式一:APIView(灵活定制接口)

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializers import OrderSerializer
from .services import OrderService
from django.core.exceptions import ValidationError

class OrderCreateAPI(APIView):
    def post(self, request):
        serializer = OrderSerializer(data=request.data)
        if serializer.is_valid():
            try:
                order = OrderService.create_order(serializer.validated_data)
                return Response(OrderSerializer(order).data, status=status.HTTP_201_CREATED)
            except ValidationError as e:
                return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

方式二:ViewSet(快速实现CRUD接口)

如果需要完整的CRUD API,可继承ViewSet并覆写create方法复用服务层逻辑:

from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from .models import Order
from .serializers import OrderSerializer
from .services import OrderService
from django.core.exceptions import ValidationError

class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        try:
            order = OrderService.create_order(serializer.validated_data)
            headers = self.get_success_headers(serializer.data)
            return Response(OrderSerializer(order).data, status=status.HTTP_201_CREATED, headers=headers)
        except ValidationError as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)

方案优势

  • 逻辑复用:Web视图和API视图共享同一套业务规则,避免重复编码和规则不一致
  • 单一职责:服务层专注业务逻辑,视图层只处理请求响应、页面渲染或数据序列化
  • 易于维护:业务规则修改只需调整服务层,无需改动多个视图
  • 可测试性:服务层可单独编写单元测试,无需依赖视图层的请求上下文

内容的提问来源于stack exchange,提问作者AhmedRaza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 11:28:15