0

0

在Python中使用Marshmallow处理POST请求并实现数据持久化

聖光之護

聖光之護

发布时间:2025-10-03 12:53:01

|

998人浏览过

|

来源于php中文网

原创

在Python中使用Marshmallow处理POST请求并实现数据持久化

本文详细阐述了如何在Python web框架(尤其是Django/DRF环境)中,利用Marshmallow库正确实现API的POST请求,以创建新对象并将其持久化到数据库。文章涵盖了数据库模型定义、Marshmallow Schema的创建与验证、以及API视图中如何集成这些组件来处理数据输入、执行业务逻辑、存储数据并返回恰当的响应,同时强调了框架原生序列化器的优势。

实现POST请求的数据持久化:Marshmallow与数据库集成

在构建restful api时,post请求是用于创建新资源的核心操作。当涉及到数据验证、序列化/反序列化以及数据持久化到数据库时,正确地组织代码结构至关重要。本文将以一个具体的案例为例,探讨如何使用marshmallow库结合数据库模型,在python环境中(特别是django/drf框架下)实现一个功能完善的post接口。

理解问题核心:缺失的数据库交互

原始实现中,尽管marshmallow的ObjectSerializer尝试对输入数据进行处理,但其create方法仅执行了super().dump(data),这本质上只是将数据序列化(或反序列化后再次序列化),而没有实际将数据保存到数据库中。这是导致“对象未添加到数据库”问题的根本原因。一个完整的POST请求流程应包括:接收请求数据 -> 验证数据 -> 将数据转换为数据库模型实例 -> 保存模型实例到数据库 -> 返回新创建对象的标识和状态。

定义数据库模型

首先,我们需要一个对应的数据库模型来存储数据。在Django框架中,这通常是一个继承自models.Model的类。这个模型将定义我们希望持久化的对象的结构和字段。

# models.py (示例:Django Model)
from django.db import models

class ObjectEntity(models.Model):
    """
    表示数据库中的一个实体对象。
    """
    operatorId = models.CharField(max_length=100, verbose_name="操作员ID")
    createdAt = models.DateField(auto_now_add=True, verbose_name="创建日期")
    operator = models.CharField(max_length=100, verbose_name="操作员名称")
    inaction = models.IntegerField(default=1, verbose_name="不活跃状态")

    class Meta:
        verbose_name = "实体对象"
        verbose_name_plural = "实体对象"

    def __str__(self):
        return f"{self.operatorId} - {self.operator}"

字段说明:

  • operatorId, operator: 字符串类型字段,用于存储操作员信息。
  • createdAt: 日期字段,auto_now_add=True会在对象首次创建时自动设置当前日期。
  • inaction: 整数字段,具有默认值1。
  • id: Django会自动为每个模型添加一个自增主键id。

优化Marshmallow Schema实现数据持久化

接下来,我们需要修改marshmallow.Schema,使其不仅能验证数据,还能与上述数据库模型进行交互,实现新对象的创建和持久化。

立即学习Python免费学习笔记(深入)”;

# serializers.py (示例:Marshmallow Schema)
from marshmallow import Schema, fields, ValidationError
# 假设 ObjectEntity 模型定义在 models.py 中,需要正确导入
# from .models import ObjectEntity 

class ObjectSchema(Schema):
    """
    用于序列化和反序列化 ObjectEntity 对象的 Marshmallow Schema。
    """
    id = fields.Integer(dump_only=True, required=False, description="对象ID,只读")
    operatorId = fields.Str(required=True, description="操作员ID")
    createdAt = fields.Date(dump_only=True, required=False, description="创建日期,只读")
    operator = fields.Str(required=True, description="操作员名称")
    inaction = fields.Integer(required=False, load_default=1, description="不活跃状态,默认为1")

    def create(self, data: dict) -> dict:
        """
        根据验证后的数据创建并持久化 ObjectEntity 对象。
        """
        try:
            # 1. 验证输入数据
            errors = self.validate(data)
            if errors:
                raise ValidationError(errors)

            # 2. 从验证后的数据中移除id和createdAt,因为它们是自动生成或只读的
            # 确保传递给create方法的数据只包含可写入的字段
            creatable_data = {
                k: v for k, v in data.items()
                if k not in ['id', 'createdAt']
            }

            # 3. 创建数据库对象
            obj = ObjectEntity.objects.create(**creatable_data)

            # 4. 序列化新创建的对象并返回
            return self.dump(obj)

        except ValidationError as err:
            # 捕获Marshmallow验证错误
            return {'errors': err.messages}
        except Exception as e:
            # 捕获其他可能的数据库或业务逻辑错误
            return {'errors': {'_general': str(e)}}

    # 注意:如果需要完整的CRUD操作,通常还会实现 update 方法
    # def update(self, instance, data):
    #     # ... 更新逻辑 ...
    #     pass

关键改进点:

Cardify卡片工坊
Cardify卡片工坊

使用Markdown一键生成精美的小红书知识卡片

下载
  • id和createdAt字段: 设置为dump_only=True。这意味着这些字段只会在序列化(从数据库到API响应)时包含,而不会在反序列化(从API请求到数据库)时被期望作为输入。required=False也进一步表明它们不是必需的输入。
  • create方法重写: 这是核心。
    • self.validate(data):首先对传入的数据进行严格验证。
    • ObjectEntity.objects.create(**creatable_data):如果数据验证通过,则使用验证后的数据创建ObjectEntity的实例并保存到数据库。creatable_data确保我们只传递模型可接受的字段。
    • self.dump(obj):成功创建并保存后,将新创建的ObjectEntity实例序列化,返回给调用者,其中将包含由数据库生成的id和createdAt。
    • 错误处理:捕获ValidationError并返回详细的错误信息。

实现API视图层

在Django REST Framework (DRF) 中,generics.ListCreateAPIView是一个非常方便的通用视图,用于处理列表查询和对象创建。我们可以将其与我们优化的ObjectSchema结合使用。

# views.py (示例:Django REST Framework View)
from rest_framework import generics
from rest_framework.request import Request
from rest_framework.response import Response
from django.http import JsonResponse
from http import HTTPStatus
import logging

# 假设 ObjectEntity 模型和 ObjectSchema 序列化器已正确导入
# from .models import ObjectEntity
# from .serializers import ObjectSchema

logger = logging.getLogger(__name__)

class ListEntityAPIView(generics.ListCreateAPIView):
    """
    处理 ObjectEntity 对象的列表查询和创建。
    """
    queryset = ObjectEntity.objects.all()
    serializer_class = ObjectSchema # 将 Marshmallow Schema 作为 DRF 的 serializer_class

    def get(self, request: Request, *args, **kwargs) -> JsonResponse:
        """
        获取所有 ObjectEntity 对象的列表。
        """
        objects = list(self.get_queryset())
        # 使用 Marshmallow Schema 序列化多个对象
        result = self.get_serializer(many=True).dump(objects)
        return JsonResponse(result, safe=False, status=HTTPStatus.OK)

    def post(self, request: Request, *args, **kwargs) -> JsonResponse:
        """
        创建新的 ObjectEntity 对象。
        """
        query_data = request.data # DRF 会自动处理请求体数据

        # 调用 Marshmallow Schema 的 create 方法来处理数据验证和持久化
        result = self.get_serializer().create(query_data)

        if 'errors' in result:
            logger.error('Error creating object: %s', str(result['errors']))
            return JsonResponse(result, status=HTTPStatus.BAD_REQUEST)

        logger.info('Object created successfully: %s', str(result))
        # 成功创建,返回新创建的对象数据和 201 Created 状态码
        return JsonResponse(result, status=HTTPStatus.CREATED)

视图层解析:

  • queryset = ObjectEntity.objects.all(): 定义了此视图操作的查询集。
  • serializer_class = ObjectSchema: 将我们自定义的Marshmallow Schema指定为DRF的序列化器。DRF的generics视图能够识别并使用这个serializer_class。
  • get方法:演示了如何使用Marshmallow Schema来序列化查询集中的多个对象。
  • post方法:
    • request.data:DRF会自动解析请求体中的JSON或表单数据。
    • self.get_serializer().create(query_data):这是核心。它实例化了ObjectSchema并调用了我们之前在ObjectSchema中定义的create方法。这个方法会负责验证数据、创建数据库记录,并返回序列化后的新对象数据或错误信息。
    • 根据create方法的返回结果,视图判断操作是否成功,并返回相应的JsonResponse和HTTP状态码(成功为201 Created,失败为400 Bad Request)。

注意事项与最佳实践

  1. Django REST Framework 原生序列化器: 虽然本教程展示了如何在DRF中使用marshmallow,但强烈建议在Django REST Framework项目中优先使用DRF自带的rest_framework.serializers.ModelSerializer。ModelSerializer与Django模型紧密集成,提供了更简洁、更强大的功能,包括自动生成字段、默认的create和update实现,以及与DRF视图的无缝协作。使用ModelSerializer可以大大减少样板代码。

    # DRF ModelSerializer 示例
    from rest_framework import serializers
    # from .models import ObjectEntity
    
    class ObjectDRFSerializer(serializers.ModelSerializer):
        class Meta:
            model = ObjectEntity
            fields = '__all__' # 自动包含模型的所有字段
            read_only_fields = ['id', 'createdAt'] # 指定只读字段
    
    # 视图中只需
    # class ListEntityAPIView(generics.ListCreateAPIView):
    #     queryset = ObjectEntity.objects.all()
    #     serializer_class = ObjectDRFSerializer

    对比之下,ModelSerializer的实现更为简洁明了。

  2. 错误处理: 确保你的API能够返回清晰、有用的错误信息。在marshmallow的create方法和视图层都应有适当的错误捕获和响应机制。返回HTTPStatus.BAD_REQUEST(400)或其他适当的错误码,并附带详细的错误描述,对于API消费者调试问题至关重要。

  3. 日志记录: 在关键操作点(如数据接收、验证失败、对象创建成功/失败)进行日志记录,有助于监控和调试API的行为。

  4. 数据校验:marshmallow提供了强大的数据校验功能。除了required=True,还可以使用validate参数添加更复杂的校验规则(如长度、格式、范围等)。

总结

通过以上步骤,我们成功地将marshmallow库与Django数据库模型和DRF视图结合起来,实现了一个功能完整的POST请求处理流程。核心在于将数据持久化的逻辑(即调用ObjectEntity.objects.create)封装到marshmallow Schema的create方法中,并确保视图层正确调用此方法。尽管marshmallow是一个优秀的通用序列化库,但在Django REST Framework的特定场景下,优先考虑使用DRF自身的ModelSerializer通常是更高效和符合框架惯例的选择。无论选择哪种工具,理解数据验证、持久化和API响应的正确流程是构建健壮API的关键。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python Web 框架 Django 深度开发
Python Web 框架 Django 深度开发

本专题系统讲解 Python Django 框架的核心功能与进阶开发技巧,包括 Django 项目结构、数据库模型与迁移、视图与模板渲染、表单与认证管理、RESTful API 开发、Django 中间件与缓存优化、部署与性能调优。通过实战案例,帮助学习者掌握 使用 Django 快速构建功能全面的 Web 应用与全栈开发能力。

167

2026.02.04

PHP API接口开发与RESTful实践
PHP API接口开发与RESTful实践

本专题聚焦 PHP在API接口开发中的应用,系统讲解 RESTful 架构设计原则、路由处理、请求参数解析、JSON数据返回、身份验证(Token/JWT)、跨域处理以及接口调试与异常处理。通过实战案例(如用户管理系统、商品信息接口服务),帮助开发者掌握 PHP构建高效、可维护的RESTful API服务能力。

179

2025.11.26

json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

457

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

549

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

337

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

82

2025.09.10

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号