Django基础教程(104)Django请求和响应之包装 API 视图:Django修炼手册:给你的API视图“美个颜”,告别又臭又长的代码!

嘿,Django的小伙伴们,今天咱们来聊点实在的,能让你下班早走半小时的干货——如何优雅地包装你的API视图

你是不是也写过这样的代码?

from django.http import JsonResponse

def my_old_api(request):
    if request.method != 'POST':
        return JsonResponse({'error': 'Method not allowed'}, status=405)
    
    try:
        data = json.loads(request.body)
        name = data['name']
        # ... 一堆业务逻辑
        return JsonResponse({'msg': f'Hello, {name}!'})
    except json.JSONDecodeError:
        return JsonResponse({'error': 'Invalid JSON'}, status=400)
    except KeyError:
        return JsonResponse({'error': 'Missing name'}, status=400)

看着就心累,对不对?像极了在菜市场跟人讨价还价,得不停地检查这个、验证那个,稍微不注意就报错。这代码,写得憋屈,看得流泪。

别慌!今天我给你请来一位“包装大师”——Django REST framework。它能让你的API视图从“路边摊”升级到“米其林三星”,不仅代码清爽,功能还贼拉强大!

第一式:神功入门,@api_view装饰器

这位“大师”带来的第一件神器,叫做 @api_view 装饰器。你可别小看这个“@”符号,它就像给你的视图函数穿上了一件“黄金圣衣”。

它主要干了三件大事:

  1. 限制HTTP方法:你明确告诉它:“哥们儿,我这个视图只接待GET和POST两位客人。” 它就会帮你把其他想闯进来的(比如PUT, DELETE)统统拦在门外,并自动返回一个漂亮的405 Method Not Allowed错误,都不用你动手!
  2. 智能解析请求:你再也不需要手动json.loads(request.body)了!DRF的Request对象会把传过来的数据(无论是JSON、表单数据还是其他格式)自动解析好,放到request.data这个“魔法字典”里。直接用就行,爽歪歪!
  3. 智能渲染响应:你也不再需要手动JsonResponse()了!你只需要返回普通的Python字典或列表,DRF的Response对象会自动帮你把它转换成客户端想要的格式(比如JSON)。

光说不练假把式,咱们直接上代码,开一家“虚拟烧烤店”吧!

场景: 我们要创建一个API,用来“点烤串”。可以查看菜单(GET),也可以下单(POST)。

第一步:安装并配置DRF

pip install djangorestframework

在你的settings.py里,把它加到INSTALLED_APPS中:

INSTALLED_APPS = [
    # ... 其他应用
    'rest_framework',
]

第二步:编写我们“包装”过的视图
views.py里:

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status

# 我们的“菜单”数据库(先临时用个列表代替)
menu = [
    {'id': 1, 'name': '羊肉串', 'price': 5},
    {'id': 2, 'name': '烤韭菜', 'price': 3},
    {'id': 3, 'name': '大腰子', 'price': 15},
]

orders = [] # 用来存订单

# 看!神奇的@api_view装饰器登场了!
@api_view(['GET', 'POST'])
def korean_barbecue(request):
    """
    烧烤店API:GET看菜单,POST下单。
    """
    # 1. 如果是客人想查看菜单(GET请求)
    if request.method == 'GET':
        # 直接返回菜单数据,Response会自动转成JSON
        return Response({'menu': menu, 'message': '欢迎光临老王烧烤!'})
    
    # 2. 如果是客人下单(POST请求)
    elif request.method == 'POST':
        # 看!这里直接用了request.data,就像用普通的字典一样!
        item_name = request.data.get('item')
        
        # 数据验证(简单的)
        if not item_name:
            return Response({'error': '哥们,你还没说要点啥呢!'}, status=status.HTTP_400_BAD_REQUEST)
        
        # 找一下点的菜在不在菜单上
        ordered_item = next((item for item in menu if item['name'] == item_name), None)
        if not ordered_item:
            return Response({'error': '抱歉,本店没有这个菜。'}, status=status.HTTP_404_NOT_FOUND)
        
        # 记录订单
        order_id = len(orders) + 1
        new_order = {'order_id': order_id, 'item': ordered_item}
        orders.append(new_order)
        
        # 返回下单成功的信息!
        return Response({
            'message': f'菜已下单!您点的{ordered_item["name"]}正在火上烤着,订单号是{order_id}。'
        }, status=status.HTTP_201_CREATED)

配置一下URL(urls.py):

from django.urls import path
from . import views

urlpatterns = [
    path('api/bbq/', views.korean_barbecue, name='bbq-api'),
]

现在,让我们来“品尝”一下这个API!

运行服务器,用浏览器访问 http://127.0.0.1:8000/api/bbq/

哇哦! 你看到了什么?不是一个干巴巴的JSON,而是一个DRF自带的可视化API界面!你可以在这个页面上直接点击进行POST操作,这就是“包装”带来的额外福利!

你用Postman或者curl测试一下POST请求:

curl -X POST http://127.0.0.1:8000/api/bbq/ -H "Content-Type: application/json" -d '{"item": "羊肉串"}'

你会收到一个优雅的响应:

{
    "message": "菜已下单!您点的羊肉串正在火上烤着,订单号是1。"
}

怎么样?是不是感觉代码瞬间清爽了,功能反而更强大了?这就是“包装”的力量!

第二式:进阶高手,APIView类

如果你的视图逻辑更复杂,比如要处理增删改查(CRUD)一整套,那么@api_view可能就显得有点“小家子气”了。这时候,就该**APIView**类闪亮登场!

APIView基于类的视图(CBV),它能把不同的HTTP方法清晰地分离到不同的类方法中,结构更清晰,也更利于复用。

来,我们把刚才的烧烤店用APIView重写一遍:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class BarbecueAPIView(APIView):
    """
    用类视图实现的烧烤店API
    """
    
    # 初始化“数据库”
    def __init__(self):
        self.menu = [...]# 同上
        self.orders = []# 同上
        super().__init__()

    # 处理GET请求
    def get(self, request, format=None):
        return Response({'menu': self.menu, 'message': '欢迎光临老王烧烤(类视图版)!'})
    
    # 处理POST请求
    def post(self, request, format=None):
        item_name = request.data.get('item')
        
        if not item_name:
            return Response({'error': '哥们,你还没说要点啥呢!'}, status=status.HTTP_400_BAD_REQUEST)
        
        ordered_item = next((item for item in self.menu if item['name'] == item_name), None)
        if not ordered_item:
            return Response({'error': '抱歉,本店没有这个菜。'}, status=status.HTTP_404_NOT_FOUND)
        
        order_id = len(self.orders) + 1
        new_order = {'order_id': order_id, 'item': ordered_item}
        self.orders.append(new_order)
        
        return Response({
            'message': f'类视图通知您:您点的{ordered_item["name"]}已下单,订单号{order_id}。'
        }, status=status.HTTP_201_CREATED)

URL配置也要相应修改:

from django.urls import path
from .views import BarbecueAPIView

urlpatterns = [
    path('api/bbq-cbv/', BarbecueAPIView.as_view(), name='bbq-api-cbv'),
]

看,用APIViewgetpost方法泾渭分明,逻辑一目了然。以后要加putdelete方法,也只是在类里新增一个函数的事儿,非常符合“高内聚、低耦合”的编程美学。

总结:给你的代码“美个颜”

好了,今天的“Django视图包装课”就到这里。我们来简单总结一下:

  • 原始Django视图:像自己买菜做饭,事事亲力亲为,虽然自由但繁琐。
  • DRF的@api_view:像请了个厨师助理,帮你处理了所有杂活(解析、渲染、检查),你只需要关心核心的“烹饪”逻辑。适合功能简单的API端点。
  • DRF的APIView:像开了一家正规餐厅,后厨分工明确(每个厨师负责一道工序),结构清晰,易于管理和扩展。适合复杂的API,尤其是完整的资源CRUD操作。

所以,别再让你辛辛苦苦写的API视图“素面朝天”了。赶紧拿起DRF这个“化妆盒”,给它“美个颜”,让它变得更强、更优雅、更好维护吧!

记住,优秀的程序员,不仅是实现功能,更是优雅地实现功能。 现在,就去重构你的代码吧!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值