Django基础教程(九十九)Django序列化之使用序列化器编写常规的视图:别再用土办法传数据了!Django序列化器带你解锁“翻译官”技能,JSON和对象无缝切换真香!

还记得刚开始用Django写API接口时,你是怎么把数据库里的对象变成JSON返回给前端的吗?是不是经常像这样“徒手拆对象”?

import json
from django.http import JsonResponse
from myapp.models import Post

def post_list(request):
    posts = Post.objects.all()
    posts_list = []
    for post in posts:
        posts_list.append({
            'id': post.id,
            'title': post.title,
            'content': post.content,
            'created_at': post.created_at.isoformat()
        })
    return JsonResponse(posts_list, safe=False)

看着这一大坨循环和字段手动映射的代码,是不是感觉自己在做“数据搬运工”?别担心,今天我要给你安利的Django序列化器(Serializer),就是来解放你生产力的!

一、序列化器到底是什么来头?

简单来说,序列化器就是个超级专业的“数据翻译官”。它负责做两件事:

  1. 序列化:把Django模型对象(比如一个Post实例)→ 转换成前端能看懂的JSON数据
  2. 反序列化:把前端发来的JSON数据 → 转换成Django模型对象

想象一下,你有个会说中英双语的翻译官。当外国朋友(前端)用英语(JSON)跟你说话时,翻译官会立刻转成中文(Django对象)让你理解;等你用中文回复后,翻译官又会贴心地转成英语告诉对方。序列化器干的就是这个活儿!

二、为什么不用土办法,非要学序列化器?

你可能会问:我手写字典不是也能用吗?来,对比一下:

土办法的痛点

  • 字段多的时候,写到手软
  • 日期格式、关联对象处理起来特别麻烦
  • 前端传数据来时,要手动校验每个字段
  • 代码重复,维护起来想哭

序列化器的爽点

  • 声明式写法,几行代码搞定复杂转换
  • 自动处理各种数据类型和关联关系
  • 内置数据验证,省去一堆if判断
  • 代码简洁,维护起来so easy

最重要的是——当你开始用序列化器,就意味着你开始用更专业的方式构建API了!

三、手把手搭建博客API实战

咱们用一个完整的博客帖子API来实战。假设你已经有了基本的Django项目和Post模型:

# models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    def __str__(self):
        return self.title
第1步:创建你的“专属翻译官”——序列化器

在Django项目中创建一个serializers.py文件:

# serializers.py
from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post  # 指定要翻译的模型
        fields = ['id', 'title', 'content', 'created_at', 'updated_at']  # 要翻译的字段

看,就这么简单!ModelSerializer是Django REST Framework给我们的神器,自动根据模型生成对应的序列化器。

第2步:编写视图——告诉“翻译官”什么时候上场

接下来,我们用最常规的基于函数的视图,实现完整的CRUD操作:

# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from .models import Post
from .serializers import PostSerializer
import json

# 获取所有帖子列表
@csrf_exempt
@require_http_methods(["GET"])
def post_list(request):
    posts = Post.objects.all()
    serializer = PostSerializer(posts, many=True)  # 多个对象要加many=True
    return JsonResponse(serializer.data, safe=False)

# 获取单个帖子详情
@csrf_exempt
@require_http_methods(["GET"])
def post_detail(request, pk):
    try:
        post = Post.objects.get(pk=pk)
    except Post.DoesNotExist:
        return JsonResponse({'error': '帖子不存在'}, status=404)
    
    serializer = PostSerializer(post)
    return JsonResponse(serializer.data)

# 创建新帖子
@csrf_exempt
@require_http_methods(["POST"])
def post_create(request):
    data = json.loads(request.body)
    serializer = PostSerializer(data=data)
    
    if serializer.is_valid():  # 自动校验数据!
        serializer.save()  # 自动创建对象!
        return JsonResponse(serializer.data, status=201)
    else:
        return JsonResponse(serializer.errors, status=400)

# 更新帖子
@csrf_exempt
@require_http_methods(["PUT"])
def post_update(request, pk):
    try:
        post = Post.objects.get(pk=pk)
    except Post.DoesNotExist:
        return JsonResponse({'error': '帖子不存在'}, status=404)
    
    data = json.loads(request.body)
    serializer = PostSerializer(post, data=data)  # 更新时要传入原对象
    
    if serializer.is_valid():
        serializer.save()
        return JsonResponse(serializer.data)
    else:
        return JsonResponse(serializer.errors, status=400)

# 删除帖子
@csrf_exempt
@require_http_methods(["DELETE"])
def post_delete(request, pk):
    try:
        post = Post.objects.get(pk=pk)
    except Post.DoesNotExist:
        return JsonResponse({'error': '帖子不存在'}, status=404)
    
    post.delete()
    return JsonResponse({'message': '删除成功'}, status=204)
第3步:配置路由

urls.py中配置路由:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('posts/', views.post_list, name='post_list'),  # 获取列表和创建
    path('posts/<int:pk>/', views.post_detail, name='post_detail'),  # 单条操作
]

四、测试你的API

现在可以用Postman或curl测试了:

获取所有帖子

GET http://localhost:8000/posts/

创建新帖子

POST http://localhost:8000/posts/
Content-Type: application/json

{
    "title": "我的第一篇博客",
    "content": "这是用Django序列化器创建的!"
}

更新帖子

PUT http://localhost:8000/posts/1/
Content-Type: application/json

{
    "title": "修改后的标题",
    "content": "更新了内容"
}

删除帖子

DELETE http://localhost:8000/posts/1/

五、序列化器的进阶玩法

1. 数据验证——你的贴心安检员

序列化器会自动帮你验证数据。比如我们的Post模型要求title不能超过200字符,如果有人传了个超长的标题:

# 这会自动触发验证错误!
data = {
    "title": "这个标题超级长..." * 50,  # 明显超长
    "content": "正常内容"
}
serializer = PostSerializer(data=data)
print(serializer.is_valid())  # False
print(serializer.errors)  # 会显示title超长的错误信息
2. 字段控制——想显示啥就显示啥

有时候你不想把所有字段都暴露出去,比如更新日期可能不想返回给前端:

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'title', 'content', 'created_at']  # 去掉了updated_at

或者只想在创建时跳过某些字段的验证:

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = '__all__'  # 包含所有字段
    
    def validate_title(self, value):
        if '广告' in value:
            raise serializers.ValidationError("标题不能包含广告词")
        return value

六、实际开发中的小贴士

  1. 性能优化:当查询列表时,记得使用select_relatedprefetch_related来避免N+1查询问题
  2. 错误处理:给前端返回统一的错误格式,比如:
{
    "success": false,
    "message": "创建失败",
    "errors": {
        "title": ["这个字段是必需的"],
        "content": ["内容不能为空"]
    }
}
  1. 分页处理:数据多了要分页,Django REST Framework有现成的分页器

七、总结

从今天起,彻底告别手动拼装JSON的苦日子吧!Django序列化器就像给你的项目请了个专业翻译官,让你能够:

✅ 用几行代码完成复杂的数据转换
✅ 自动获得数据验证,少写一堆if else
✅ 轻松维护,字段变更只需改一个地方
✅ 代码更专业,更符合RESTful规范

最重要的是,你终于可以从繁琐的数据搬运中解放出来,专注于更重要的业务逻辑了!


本文示例代码在Django 3.2 + Django REST Framework 3.12环境下测试通过。不同版本可能略有差异,但核心概念相通。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

值引力

持续创作,多谢支持!

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

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

打赏作者

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

抵扣说明:

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

余额充值