ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

drf框架序列化和返序列化

2019-09-03 20:57:02  阅读:216  来源: 互联网

标签:obj 框架 user pk serializers 序列化 data drf


0903自我总结

drf框架序列化和返序列化

from rest_framework import serializers

一.自己对于序列化和返序列化使用的分类

前后端交互主要有get,post,puch,put,deleter

其中用到序列化的get

用到返序列化的剩下四中

二.序列化的使用

1.首先我们要根据我们定义的模型一一对应定义一个继承serializers.Serializer的类

class UserSerializer(serializers.Serializer):
    username = serializers.CharField()
    #不需要的字段=serializers.CharField(write_only=True)
    sex = serializers.IntegerField()
    gender = serializers.SerializerMethodField()
    def get_gender(self, user_obj):
        return user_obj.get_sex_display()
    icon = serializers.SerializerMethodField()
    def get_icon(self, user_obj):
        icon_url = 'http://127.0.0.1:8000{}{}'.format(settings.MEDIA_URL, user_obj.icon)
        return icon_url

需要序列化字段

  • 在不做任何处理的情况下我们定义的类里面的字段必须在model类中必须存在该字段
  • 参与序列化的属性名必须与model类的属性相同
  • 只出现在序列化中不出现在返序列化中我们要加只读属性read_only=True

不需要序列化字段

  • 不需要序列化的属性字段在序列化类中不需要声明
  • 不需要序列化的属性字段在序列化类中设置只写属性write_only=True

需要对序列化字段进行二次修改的

基于GET请求的get_
def get_model类中有字段(self,obj):
    #逻辑处理
    return 修改后的代码

2.在views视图中

from rest_framework.views import APIView
class UserAPIView(APIView):
     def get(self, request, *args, **kwargs):
        user_obj = models.User.objects.all().frist
        user_obj_data = '''我们自定义的Serializer类'''(user_obj).data
        return APIResponse(0, 'ok', results=user_obj_data)
  • 获取models中的对象
  • 我们自定义的Serializer类传入models中的对象然后.data
  • 如果models中对象为多个Serializer传入models中的对象以外many=True还需传入这个参数
  • many这个参数默认是False所有我们序列化单个参数时候不需要传入many
  • 序列化数据可以为状态User类的多个对象的单列集合,不能是多列集合

:

  • 单列集合[a,b,c.....] |{a,b,c.....}|(a,b,c.....)|QuerySet
  • 多列集合{k1:v1,k2:v2.......}

三反序列化的使用

1.首先我们要根据我们定义的模型一一对应定义一个继承serializers.Serializer的类

class UserDeserializer(serializers.Serializer):
    username = serializers.CharField(
        min_length=3,
        error_messages={
            'min_length': '用户名太短'
        }
    )
    password = serializers.CharField(
        min_length=3,
        error_messages={
            'min_length': '密码太短'
        }
    )
    re_password = serializers.CharField(
        min_length=3,
        required=True,
        error_messages={
            'min_length': '确认密码太短',
            'required': '确认密码不能为空'
        }
    )

相较于序列化定义反序列化中增加了条件的筛选

注意点:如果类的字段值应用在反序列化,我们可以在他的字段的属性上加上write_only=True

里面所提及的字段必须传入

常用的约数条件与django中from组件约数条件有点类似:

  • error_messages 错误信息的属性
  • required是否为空
  • max_length 最长
  • min_length 最短
  • invalid 格式

局部钩子

class UserDeserializer(serializers.Serializer):
    .......
    def validate_字段名称(self,value):
        #代码块
        if 情况不满足:
            raise serializers.ValidationError('异常信息') #抛出异常
            return value
        #也就是对字段数据进行二次处理

全局钩子

 class UserDeserializer(serializers.Serializer):
    .......
    def validate(self, attrs):
        #attrs是所有字段的一个类似字典的集合
        #我们要其中某个字段
        attrs.get('字段名')
        return attrs
       # 最终结果抛出异常或者返回attrs

2.内容新增使用

我们必须要在Serializer类中再加个create方法

class UserDeserializer(serializers.Serializer):
    .......
    def create(self, validated_data):
        try:
            return modles中的类.objects.create(**validated_data)
        except:
            raise IOError('数据库入库失败')

我们更具需求可以先自定义一个APIResponse,继承rest_framework中的Response也可以直接使用他自带的

自定义APIResponse,建议自定义

from rest_framework.response import Response
"""
Response({
    'status': 0,
    'msg': 'ok',
    'results': [],
    'token': ''
}, headers={}, status=200, content_type="")

APIResponse(0, 'ok', results, status, headers, content_type)
"""

class APIResponse(Response):
    def __init__(self, data_status, data_msg, results=None,
                 status=None, headers=None, content_type=None, **kwargs):
        data = {
            'status': data_status,
            'msg': data_msg
        }
        if results is not None:
            data['results'] = results
        data.update(kwargs)
        super().__init__(data=data, status=status, headers=headers, content_type=content_type)

在视图函数中的设置

class UserAPIView(APIView):
    def post(self, request, *args, **kwargs):  #一般都是post请求
        request_data = request.data
        user_ser = '''我们自定义的Serializer类'''(data=request_data) #传入request.data
        
        
        if user_ser.is_valid():  # 自定义处理校验成功的逻辑
            user_obj = user_ser.save()
            return APIResponse(0, 'ok',
                results=serializers.UserSerializer(user_obj).data
            )
        else:  # 自定义返回错误信息
            return APIResponse(1, 'failed', results=user_ser.errors)

3.内容修改使用

我们必须要在Serializer类中再加个create方法

class UserDeserializer(serializers.Serializer):
         .......
    def update(self, instance, validated_data):
        # instance自定义传入的要更新的原数据(pk | obj | queryset)
        # validated_data校验通过后的新数据
        # instance的值外部反序列化传入要更新的自定义标识决定
        instance.update(**validated_data)
        return instance.first()

在视图函数中的设置

单整体改

class UserV2APIView(APIView):
    
    def put(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        if not pk:
            return APIResponse(1, 'pk error')

        user_query = models.User.objects.filter(pk=pk, is_delete=False)
        if not user_query:
            return APIResponse(1, 'user error')

        # 第一种:user_query完成数据的更新
        # user_query = models.User.objects.filter(pk=pk)
        # user_query.update(**kwargs)

        # 第二种:user_obj完成数据的更新
        # user_obj = models.User.objects.filter(pk=pk).first()  # type: models.User
        # user_obj.username = 'new_username'
        # ...
        # user_obj.save()
  

       #这里的instance必须传参(pk | obj | queryset)
        request_data = request.data
        user_ser = serializers.UserV2Serializer(instance=user_query, data=request_data)
        if user_ser.is_valid():
            # save的返回值是由update内部自定义的返回值决定
            user_obj = user_ser.save()
            return APIResponse(0, 'ok',
                results=serializers.UserV2Serializer(user_obj).data
            )
        else:
            return APIResponse(1, 'failed', user_ser.errors)

单删单体修改

现在数据都是很重要的一般情况下不会吧数据删除只会做个标记字段其本质还是局部更新

    def delete(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        if not pk:
            return APIResponse(1, 'pk error')
        user_obj = models.User.objects.filter(pk=pk, is_delete=False).first()
        if not user_obj:
            return APIResponse(1, '删除失败')
        user_obj.is_delete = True
        user_obj.save()
        return APIResponse(0, '删除成功')

四.model字段修订与时区修改

model.py

    create_time = models.DateTimeField(auto_now_add=True, null=True)
    is_delete = models.BooleanField(default=False)

setting.py

时区相关设置

LANGUAGE_CODE = 'zh-hans'   #其中 zh-Hans是简体中文  zh-Hant是繁体中文

TIME_ZONE = 'Asia/Shanghai'  #上海时间

USE_I18N = True   #国际化支持 I18N

USE_L10N = True

USE_TZ = False   #USE_TZ设置为True,Django会使用系统默认设置的时区即America/Chicago,此时的TIME_ZONE不管有没有设置都不起作用。

注意点:

USE_TZ为True,TIME_ZONE不管有没有设置都不起作用

标签:obj,框架,user,pk,serializers,序列化,data,drf
来源: https://www.cnblogs.com/pythonywy/p/11455508.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有