drf序列化器与反序列化_weixin_38166689的博客-程序员秘密

技术标签: python  数据库  

什么是序列化与反序列化

"""
序列化:对象转换为字符串用于传输
反序列化:字符串转换为对象用于使用
"""

drf序列化与反序列化

"""
序列化:Model类对象转换为字符串用于传输
反序列化:字符串转换为Model类对象用于使用
"""

Model类

创建数据库:终端
>: mysql -uroot -p密码
>: create database 数据库名 charset=utf8
配置数据库:settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '数据库名',
        'USER': 'root',
        'PASSWORD': '密码'
    }
}
修改操作数据库的模块:项目init文件
import pymysql
pymysql.install_as_MySQLdb()
创建model类:models.py
from django.db import models
class User(models.Model):
    CHOICE_SEX = (
        (0, '男'),
        (1, '女')
    )
    name = models.CharField(max_length=32, verbose_name='姓名')
    password = models.CharField(max_length=64, verbose_name='密码')
    sex = models.SmallIntegerField(choices=CHOICE_SEX, default=0)
    create_time = models.DateTimeField(auto_now_add=True, blank=True)

    class Meta:
        # 自定义创建的表名
        db_table = 'o_user'
        # admin界面中显示的表面与表名复数形式
        verbose_name = '用户'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name
注册model类:admin.py
from django.contrib import admin
from api.models import User
admin.site.register(User)
数据库迁移:在项目目录下的终端
>: python3 manage.py makemigrations
>: python3 manage.py migrate
注册超级用户:在项目目录下的终端
>: python3 manage.py createsuperuser
登陆admin页面添加数据:浏览器
http://localhost:8000/admin/

路由分发

项目urls.py
from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include('api.urls'))
]
api应用urls.py
from django.conf.urls import url
urlpatterns = [

]

获取多资源 接口

序列化类:serializers.py
from rest_framework import serializers

# 为每一个Model类至少配一个Serializer类
class UserSerializer(serializers.Serializer):
    # 序列化一个Model类对象,其实就是序列化该类的每一个属性
    name = serializers.CharField()
    password = serializers.CharField()
    sex = serializers.IntegerField()
    create_time = serializers.DateTimeField()
视图类:views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import User
from .serializers import UserSerializer

# 对应路由:/users/
# 功能:get获取所有 | post新增一个 | put修改一个 | delete删除一个
class UsersAPIView(APIView):
    def get(self, request, *args, **kwargs):
        user_list = User.objects.all()
        
        # instance存放的是queryset对象,many需要设置为True
        user_data = UserSerializer(instance=user_list, many=True).data
        return Response(
            {
                'status': 0,
                'msg': 'ok',
                'results': user_data
            }
        )

序列化字段操作(自定义字段)

序列化类修订:serializers.py
from rest_framework import serializers

# 为每一个Model类至少配一个Serializer类
class UserSerializer(serializers.Serializer):
    # 序列化一个Model类对象,其实就是序列化该类的每一个属性
    # 注意1:Model类与Serializer类是通过属性名建立关联的 - 属性名必须依照
    name = serializers.CharField()
    password = serializers.CharField()
    # sex = serializers.IntegerField()
    # 注意2:不需要通过给前台的数据,不需要提供该属性的序列化
    # create_time = serializers.DateTimeField()

    # 注意3:serializers.SerializerMethodField()可以产生自定义序列化属性(不需要和Model类属性同步),
    #       但要为其绑定一个提供值的函数,函数名为 get_属性(self, obj) (obj为参与序列化的Model类对象)
    gender = serializers.SerializerMethodField()
    def get_gender(self, obj):
        # 该函数的返回值就作为对应自定义数据序列化后的值
        return obj.get_sex_display()

新增单资源 接口

序列化类(反序列化类):serializers.py
from rest_framework import serializers
from .models import User


class UserDeserializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=32, min_length=3, error_messages={
        'max_length': '姓名太长',
        'min_length': '姓名太短'
    })
    password = serializers.CharField(label='密码', max_length=64, min_length=3, error_messages={
        'max_length': '密码太长',
        'min_length': '密码太短'
    })
    sex = serializers.IntegerField()
    # required=False该字段前台可以不用传(不参与校验)
    create_time = serializers.DateTimeField(required=False)

    # 完成ORM的操作
    # def save(self):  # 不能直接重写save,因为系统的save可以完成新增或修改
    #     # print(self.validated_data)
    #     User.objects.create(**self.validated_data)

    # 为post接口提供新增Model类对象的功能
    def create(self, validated_data):
        # 返回值:Model类要新增的对象
        return User.objects.create(**validated_data)
视图类:views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import User
from .serializers import UserSerializer

# 对应路由:/users/
# 功能:get获取所有 | post新增一个 | put修改一个 | delete删除一个
class UsersAPIView(APIView):
    # 新增一个资源
    def post(self, request, *args, **kwargs):
        user_deser = UserDeserializer(data=request.data)
        # raise_exception值为True,当校验失败,直接返回校验失败的错误信息
        # result = user_deser.is_valid(raise_exception=True)
        result = user_deser.is_valid()
        if result:
            new_user_obj = user_deser.save()
            return Response({
                'status': 0,
                'msg': 'success',
                'result': UserSerializer(new_user_obj).data
            })
        else:
            return Response({
                'status': 1,
                'msg': 'failed',
                'results': user_deser.errors
            })

更新单资源 接口

序列化类(反序列化类):serializers.py
from rest_framework import serializers
from .models import User


class UserDeserializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=32, min_length=3, error_messages={
        'max_length': '姓名太长',
        'min_length': '姓名太短'
    })
    password = serializers.CharField(label='密码', max_length=64, min_length=3, error_messages={
        'max_length': '密码太长',
        'min_length': '密码太短'
    })
    sex = serializers.IntegerField()
    # required=False该字段前台可以不用传(不参与校验)
    create_time = serializers.DateTimeField(required=False)

    # 完成ORM的操作
    # def save(self):  # 不能直接重写save,因为系统的save可以完成新增或修改
    #     # print(self.validated_data)
    #     User.objects.create(**self.validated_data)

    # 为post接口提供新增Model类对象的功能
    def create(self, validated_data):
        # 返回值:Model类要新增的对象
        return User.objects.create(**validated_data)
    
    # 为put接口提供更新Model类对象的功能
    def update(self, instance, validated_data):
        # 操作model对象
        # instance.name = validated_data.get('name')
        # instance.password = validated_data.get('password')
        # instance.sex = validated_data.get('sex')
        # instance.save()
        # 操作queryset对象
        instance.update(**validated_data)
        return instance
视图类:views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import User
from .serializers import UserSerializer

# 对应路由:/users/
# 功能:get获取所有 | post新增一个 | put修改一个 | delete删除一个
class UsersAPIView(APIView):
    # 更新一个资源
    def put(self, request, *args, **kwargs):
        # 要更新的资源的主键
        pk = kwargs.get('pk')
        
        # 操作更新时可以选择操作 queryset对象 或 model对象
        # 操作model对象
        # old_user_obj = User.objects.get(pk=pk)
        # user_deser = UserDeserializer(instance=old_user_obj, data=request.data)

        # 操作queryset对象
        old_user_query = User.objects.filter(pk=pk)
        user_deser = UserDeserializer(instance=old_user_query, data=request.data)

        # raise_exception值为True,当校验失败,直接返回校验失败的错误信息
        # result = user_deser.is_valid(raise_exception=True)
        result = user_deser.is_valid()
        if result:
            # new_user_obj = user_deser.save()  # 操作model对象
            new_user_query = user_deser.save()  # 操作queryset对象
            new_user_obj = new_user_query.first()
            return Response({
                'status': 0,
                'msg': 'success',
                'result': UserSerializer(new_user_obj).data
            })
        else:
            return Response({
                'status': 1,
                'msg': 'failed',
                'results': user_deser.errors
            })

删除单资源 接口

重构Model新增字段:models.py
class User(models.Model):
    CHOICE_SEX = (
        (0, '男'),
        (1, '女')
    )
    name = models.CharField(max_length=32, verbose_name='姓名')
    password = models.CharField(max_length=64, verbose_name='密码')
    sex = models.SmallIntegerField(choices=CHOICE_SEX, default=0)
    create_time = models.DateTimeField(auto_now_add=True, blank=True)
    # 新增:数据删除不是从数据库删除记录,而是修改记录状态,标示为已删除即可
    is_delete = models.BooleanField(default=False)

    class Meta:
        # 自定义创建的表名
        db_table = 'o_user'
        # admin界面中显示的表面与表名复数形式
        verbose_name = '用户'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name
数据库迁移:在项目目录下的终端
>: python3 manage.py makemigrations
>: python3 manage.py migrate
视图类接口:views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import User
from .serializers import UserSerializer

# 对应路由:/users/
# 功能:get获取所有 | post新增一个 | put修改一个 | delete删除一个
class UsersAPIView(APIView):
    # 删除一个资源
    def delete(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        try:
            delete_user_obj = User.objects.get(pk=pk, is_delete=False)
            # 完成删除信息的更新
            delete_user_obj.is_delete = True
            delete_user_obj.save()
            return Response()
        except:
            return Response({
                'status': 1,
                'msg': '数据删除失败'
            })

获取单资源 接口

序列化类:serializers.py
from rest_framework import serializers

# 为每一个Model类至少配一个Serializer类
class UserSerializer(serializers.Serializer):
    # 序列化一个Model类对象,其实就是序列化该类的每一个属性
    name = serializers.CharField()
    password = serializers.CharField()
    sex = serializers.IntegerField()
    create_time = serializers.DateTimeField()
视图类:views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import User
from .serializers import UserSerializer

# 对应路由:/users/
# 功能:get获取所有 | post新增一个 | put修改一个 | delete删除一个
class UsersAPIView(APIView):
    def get(self, request, *args, **kwargs):
         pk = kwargs.get('pk', None)

        if not pk:
            user_query = User.objects.filter(is_delete=False).all()
        else:
            user_query = User.objects.filter(is_delete=False, pk=pk)
            # 如果只操作一个对象,many参数需要为False(默认值)
            # user_obj = User.objects.filter(is_delete=False, pk=pk).first()
            # user_data = UserSerializer(instance=user_obj, many=False).data

        user_data = UserSerializer(instance=user_query, many=True).data
        return Response(
            {
                'status': 0,
                'msg': 'ok',
                'results': user_data
            }
        )

序列化基础:重点内容

模型类:models.py
from django.db import models

# Create your models here.

class User(models.Model):
    CHOICE_SEX = (
        (0, '男'),
        (1, '女')
    )
    name = models.CharField(max_length=32, verbose_name='姓名')
    password = models.CharField(max_length=64, verbose_name='密码')
    sex = models.SmallIntegerField(choices=CHOICE_SEX, default=0)
    create_time = models.DateTimeField(auto_now_add=True, blank=True)
    # 数据删除不是从数据库删除记录,而是修改记录状态,标示为已删除即可
    is_delete = models.BooleanField(default=False)

    class Meta:
        # 自定义创建的表名
        db_table = 'o_user'
        # admin界面中显示的表面与表名复数形式
        verbose_name = '用户'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name
序列化类:
from rest_framework import serializers
from .models import User

class UserSerializer(serializers.Serializer):
    # 序列化和反序列化都可以使用
    name = serializers.CharField(label='姓名', max_length=32, min_length=3, error_messages={
        'max_length': '姓名太长',
        'min_length': '姓名太短'
    })
    password = serializers.CharField(label='密码', max_length=64, min_length=3, error_messages={
        'max_length': '密码太长',
        'min_length': '密码太短'
    })
    # 只有反序列化使用 - 用 write_only=True 标示只参与反序列化
    sex = serializers.IntegerField(write_only=True)
    # 只有序列化使用 - 自定义字段 - 用 read_only=True 标示只参与序列化
    gender = serializers.SerializerMethodField(read_only=True)
    def get_gender(self, obj):
        return obj.get_sex_display()
    # 序列化与反序列化都不使用 - 1)注释 | 2)required=False, write_only=True
    create_time = serializers.DateTimeField(required=False, write_only=True)

    # 为全局校验钩子新增校验字段
    re_password = serializers.CharField(label='确认密码', max_length=64, min_length=3, write_only=True, error_messages={
        'max_length': '确认密码太长',
        'min_length': '确认密码太短'
    })


    # 反序列化两大方法重写 - 新增create | 更新update
    # 为post接口提供新增Model类对象的功能
    def create(self, validated_data):
        # 返回值:Model类要新增的对象
        return User.objects.create(**validated_data)

    # 为put接口提供更新Model类对象的功能
    def update(self, instance, validated_data):
        instance.update(**validated_data)
        # 返回更新后的instance
        return instance


    # 局部钩子
    def validate_sex(self, value):
        if value not in (0, 1):
            raise serializers.ValidationError('未知性别')
        return value

    # 全局钩子
    def validate(self, attrs):
        re_password = attrs.pop('re_password')
        password = attrs.get('password')
        if re_password != password:
            raise serializers.ValidationError('二次密码不一致')
        return attrs
视图类:
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import User
from .serializers import UserSerializer

# 对应路由:/users/ | /users/pk/
# 功能:get获取所有 | post新增一个 | put修改一个 | delete删除一个 | get获取一个
class UsersAPIView(APIView):
    # 获取所有资源 | 单个资源
    def get(self, request, *args, **kwargs):
        # 单个资源的主键
        pk = kwargs.get('pk', None)
        if not pk:
            user_query = User.objects.filter(is_delete=False).all()
        else:
            user_query = User.objects.filter(is_delete=False, pk=pk)

        user_data = UserSerializer(instance=user_query, many=True).data
        return Response(
            {
                'status': 0,
                'msg': 'ok',
                'results': user_data
            }
        )

    # 新增一个资源
    def post(self, request, *args, **kwargs):
        user_deser = UserSerializer(data=request.data)

        # raise_exception值为True,当校验失败,直接返回校验失败的错误信息
        # result = user_deser.is_valid(raise_exception=True)
        result = user_deser.is_valid()
        if result:
            new_user_obj = user_deser.save()
            return Response({
                'status': 0,
                'msg': 'success',
                'result': UserSerializer(new_user_obj).data
            })
        else:
            return Response({
                'status': 1,
                'msg': 'failed',
                'results': user_deser.errors
            })

    # 更新一个资源
    def put(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        old_user_query = User.objects.filter(pk=pk, is_delete=False)
        # 没有数据
        if not old_user_query:
            return Response({
                'status': 1,
                'msg': 'update failed',
            })

        user_deser = UserSerializer(instance=old_user_query, data=request.data)
        result = user_deser.is_valid()
        if result:
            new_user_query = user_deser.save()
            new_user_obj = new_user_query.first()
            return Response({
                'status': 0,
                'msg': 'success',
                'result': UserSerializer(new_user_obj).data
            })
        else:
            return Response({
                'status': 1,
                'msg': 'failed',
                'results': user_deser.errors
            })

    # 删除一个资源
    def delete(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        try:
            delete_user_obj = User.objects.get(pk=pk, is_delete=False)
            # 完成删除信息的更新
            delete_user_obj.is_delete = True
            delete_user_obj.save()
            return Response()
        except:
            return Response({
                'status': 1,
                'msg': '数据删除失败'
            })

转载于:https://www.cnblogs.com/huanghongzheng/p/11373700.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_38166689/article/details/101790305

智能推荐

MYSQL安装和初始化配置_一梦如是YFL的博客-程序员秘密

简介:MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件。MySQL是一种关系数据库管理系统,关系数据库将数据保存在不同的表中,...

Effective C++条款14:在资源管理类中小心拷贝行为_efective c++ 拷贝控制_却道天凉_好个秋的博客-程序员秘密

前言在前面的文章中我们介绍了智能指针类来管理资源,但是对于某些资源,它们不是动态分配的(不是堆上的),因此智能指针就是不适合这种资源的管理了,因此你可能会设计自己的资源管理类一、“不希望拷贝”演示案例假设我们使用C的API函数处理类型为Mutex的互斥器对象,其中有两个函数如下: void lock(Mutex* pm); //锁定pm所指的互斥器 void unlock(Mutex* pm); //将互斥器解锁 现在我们设计一个类,来管理Mutex对象,并且使用了上一.

一个程序员的2014技术学习总结_chuifuhuo6864的博客-程序员秘密

2014年读了14本书 读完的9本 《Javascript 语言精粹》,《Javascript functional Programming》,《MacTalk 人生元编程》,《代码未来》,《少有人走的路》,《The Magic Finger》,《Objec...

Android签名证书 keystore jks pem x509_LeonLambert的博客-程序员秘密

Android签名证书背景因业务需求,经常与系统厂商打交道,大多需要厂商开放root权限目前获取系统权限的总结有三种方式(均有实际应用)platform签名root固件 (有su)调用厂商封装好的系统权限的sdk后两者调试比较简单,不多做介绍. 针对第一点,厂商会提供两个文件​ platform.pk8 保存private key 加密...

为tornado自定义session_Ayhan_huang的博客-程序员秘密

cookie和session在自定义session前,我们需要先了解cookie和session是什么,可以参考我之前的博客:http://blog.csdn.net/ayhan_huang/article/details/78032097简单来说:cookie是保存在浏览器的键值对session是保存在服务端的键值对session依赖于cookie在Django框架中,我们可以直接操作co

PicGo安装插件一直显示“安装中”_go安装器一直显示努力安装中_Vladimir__的博客-程序员秘密

原因:插件安装需要使用npm命令,npm命令对于安装的操作需要使用管理员权限,当前windows账户的权限不足就会导致插件一直处于”安装中“状态。解决方案:修改windows账户权限【WIN+R】组合键打开运行,输入gpedit.msc打开”本地组策略编辑器“,依次打开”计算机配置“、”Windows设置“、”安全设置“、”本地策略“、”安全选项“,找到”用户访问控制:以管理员批准模式运行所有管理员“,右键打开属性,选择”已禁用“,点击确定,重启计算机,然后重新安装PicGo插件。使用管理员

随便推点

js把txt转为html,js格式化文本为html标签_胡千山的博客-程序员秘密

问题背景:表单长文本字段填写无引入富文本编辑器,使用textarea输入,打印表单时,将文本放至表格td内,无法保留textarea的内容格式。主要问题表现为:①换行符变为空格展示,没有换行显示。②多个空格变为单个空格显示。问题解决:/*** 格式化文本为html标签* contentId,需进行格式转换的元素ID**/function formatText(contentId){var cont...

【lombok】@Cleanup - 自动资源管理,安全的调用close方法_Amos-Chen的博客-程序员秘密

@Cleanup当在处理文件对象,或者数据库资源时,我们总是会忘记close,可能引发内存溢出。如果手动去调用close方法,代码又会非常长,现在有了@Cleanup , 我们不再需要担心这些问题。您可以使用@Cleanup确保在代码执行路径退出当前作用域之前自动清除给定资源。 您可以通过使用@Cleanup注释来注释任何局部变量声明来执行此操作,如下所示:@Cleanup Inpu...

一个杂项设备,应用层通过write函数传入一个结构体,把结构体写入内核_weixin_44317448的博客-程序员秘密

#1杂项设备##1.1linux下的三大设备字符设备,块设备,网络设备。字符设备特点:是一个顺序的数据流设备,对这种设备的读写是按字符进行的,这些字符是连续地形成一个数据流。他不具备缓冲区,对这种设备的读写是实时的。块设备特点:具有一定结构的随记存取设备,对这种设备的读写是按块进行的,使用缓冲区来存放暂时的数据,待时机成熟后,从缓存一次性写入设备或者从设备一次性读到缓冲区。网络设备特点:...

怎么解决IE11的textarea不换行这个BUG(转)_yzy85的博客-程序员秘密

原文地址:https://www.php.cn/js-tutorial-387902.html这次给大家带来怎么解决IE11的textarea不换行这个BUG,我们知道textarea在ie11下,内容超出文本框后就不换行了,那么,解决IE11的textarea不换行BUG的注意事项有哪些?下面就是实战案例,一起来看一下。textarea{ white-space:pre-wrap; /* css3.0 */ white-space:-moz-pre-wrap; /* Firef

java多媒体框架(JMF)的processor处理器 api中英文翻译_桃根仙的博客-程序员秘密

原文:javax.media Interface Processorpublic interface Processorextends PlayerThe Processor interface defines a module for processing and controlling time-based media data. Processor extends the P...

个人对指针的理解,欢迎大家批评_专注客户端技术的博客-程序员秘密

指针对应着某个数据在内存空间中的地址。我们通过存放某地址的指针,来使用*指针名 来引用 地址为指针值的内存块上的数据。因为内存块会委托给变量,所以这个数据会和某变量值绑定。所以说通过指针可以修改某地址的变量的值。             我们可以这样理解指针,指针可以存放地址,而且可以根据指针值即地址和指针所指向的类型来获取地址为 指针值的前 sizeof(指针所指向的类型) 个字节的

推荐文章

热门文章

相关标签