序列化组件:Serializer、ModelSerializer、ListModelSerializer

Serializer  偏底层  ModelSerializer       重点  ListModelSerializer     辅助群改

1.Serializer组件

(1)准备

(1)models.py中

class User(models.Model):
SEX_CHOICES = [
[0,”男”], #前面是0还是”0”和IntergerField还是CharField有关
[1,”女”] #前面是填入的,后面是显示的
]
name = models.CharField(max_length=64)
pwd = models.CharField(max_length=32)
phone = models.CharField(max_length=11, null=True, default=None)
sex = models.IntegerField(choices=SEX_CHOICES, default=0)
icon = models.ImageField(upload_to=”icon”, defult=’icon/defult.png’) #需要在项目base目录下新建media文件夹,然后在media下建立icon文件夹
  (默认会找media下的icon文件夹)
class Meta:
db_table = ‘yq_user’
verbose_name = “用户表”
verbose_name_plural = verbose_name
def __str__(self):
return “%s”%self.name

(2)在admin.py下注册User

admin.site.register(models.User)

(3)在shell中迁移

makemigrations、migrate

get请求是要序列化,将后台数据返回给前台;post请求要反序列化,将前台数据给后台存入数据库中,同时也要序列化对象展示数据给前台。

(4)配置媒体资源

1)在settings.py里配置media路径

MEDIA_ROOT = os.path.join(BASE_DIR, ‘media’)

2)在项目文件下的urls.py中

#media在根路由配置

from django.views.static import serve
from django.conf import setting urlpatterns = [
...
url(r”^media/(?P<path>.*)”, serve, {‘document_root’: setting.MEDIA_ROOT}) #正则匹配时不要写$,可以一层层找
]

3)数据库再迁移下

用户对象(model对象或者query_set对象)、用户对象列表不能直接返回给前台,要序列化下对象。因此要用Serializer。

(2)序列化

(1)配置路由

urlpatterns = [
url(r'^users/$', views.User.as_view()),
url(r'^users/(?P<pk>.*)/$', views.User.as_view()),
]

(2)自定义序列化类。在应用文件夹下新建serializers.py文件。

序列化组件的工作方式与django的forms组件相似

from rest_framework import serializers

class UserSerailizer(serializers.Serializer):

  #字段的类型和定义时一致,字段为想要返回给前台的内容(pwd不用返回就不写)
  name = serializers.CharField() #序列化的括号里不需加条件
  phone = serlializers.CharField()
  #sex = serializers.IntegerField()
  #icon = serializers.ImageField()   #由于sex默认返回的是0、1数字给前台,icon返回的不是全链接,因此要自定义序列化属性:定制返回的内容   gender = serializers.SerializerMethodField() #可以叫gender,也可以叫sex,不一定与字段名保持一致   def get_gender(self, obj): #必须以get开头,后面也必须和上面的gender对应
  #self是serializer对象,obj是模型类对象
    return obj.get_sex_display() #get_xxx_display() 表示取到选项值   #在settings.py中配置下MEDIA_URL = /media/
  from untitled1 import settings
  img = serializer.SerializerMethodField()
  def get_img(self, obj):
    return “%s%s%s”%(r”http://127.0.0.1:8000”, settings.MEDIA_URL, str(obj.icon))
  #obj.icon不能直接作为数据返回,类型是ImageFile类型,可以通过str转化为str类型。

(3)在views.py中返回对象序列化后的json数据

from . import serializers
from rest_framework.views import APIView
from rest_framework.response import Response class User(APIView): def get(self, request, *args, **kwargs):
pk = kwargs.get('pk') #通过有名分组匹配到的路径参数
if pk: #单查
try:
user_obj = models.User.objects.get(pk=pk) #取到model对象
#将对象序列化取得dict数据
user_ser_data = serializers.UserSerializer(user_obj).data
return Response({
"status": 0,
"msg": "ok",
"results": user_ser_data
})
except:
return Response({
"status": 2,
"msg": "no user",
})
else: #群查
user_obj_list = models.User.objects.all()
       #将对象列表序列化
user_ser_data = serializers.UserSerializer(
user_obj_list,many=True).data
return Response({
"status": 0,
"msg": "ok",
"results":user_ser_data
})

总结:

序列化ser:

1)序列化给前台的字段个数可以由后台自己决定,但是提供的序列化字段的一定要和数据库的字段的类型和名字一致。

2)自定义属性名:为了返回自定义的字段的值。属性名随意,值由固定的命名规范方法提供:get_属性名(self, obj)。obj为参与序列化的model或者query_set对象。返回值就是自定义序列化属性的值。

view:

1)从数据库中将要序列化给前台的model对象,或是多个model对象查询出来

user_obj = models.User.objects.get(pk=pk)或者

user_objs_list = models.User.objects.all()

2)将对象交给序列化处理,产生序列化对象,如果序列化的是多个数据,要设置many=True

user_ser = serializers.UserSerializer(user_obj)或者

user_ser_list = serializers.UserSerializer(user_objs_list, many=True)

3)序列化对象.data就是可以返回给前台的序列化数据,然后return Response返回

(3)反序列化

反序列化考虑的问题:

1)哪些字段必须反序列化

2)字段都有哪些安全校验

3)哪些字段需要提供额外的安全校验

4)哪些字段间存在联合校验

反序列化字段全都是用来入库的,不会出现自定义方法属性,但会出现设置校验规则(系统校验、局部钩子和全局钩子)的自定义属性(如re_pwd)

(1)还是在刚才的serializers.py文件中

class UserDeserializer(serializer.Serializer):

  name = serializers.CharField(
   required=True,
   max_length=64, #自定义检验规则
   min_length=3,
   error_message = { #错误信息,不给是默认的
       ‘max_length’:’太长’,
      ‘min_length’:’太短’,
})
  pwd= serializers.CharField(required=True)
  phone = serializers.CharField(required=False)
  sex = serializers.IntegerField(required=False)   #自定义有校验规则的反序列化字段。不存入库,只是用来校验
  re_pwd = serializers.CharField(required=True) #用来判断两次输入密码一样   #局部钩子:validate_要校验的字段名(self, 当前要检验字段的值)
  #校验规则:校验成功返回原值,失败返回异常
  #局部钩子校验某个字段
  def validate_name(self, value):
    if ‘j’ in value.lower(): #名字中不能出现j
     #from rest_framework import exceptions
      raise exceptions.ValidationError(“名字非法”)
    return value #必须返回,校验成功返回value,失败抛异常   #全局钩子:固定写法validate(self, attrs)。attrs为系统与局部钩子校验通过的所有数据。(系统和全局之间还有个局部钩子)
  #校验时需要用到多个字段。比如两次密码输入一致
  #校验规则:校验成功返回原值,失败返回异常
  def validate(self, attrs):
    pwd = attrs.get(‘pwd’) #只是取得
    re_pwd = attrs.pop(‘re_pwd’) #取得并且删除(不需要入库)
    if pwd != re_pwd:
      raise exceptions.ValidationError({“pwd“: “两次密码不一致”})
    return attrs #必须返回,校验成功返回attrs,失败抛异常   #要完成新增,需在serializers.py中的自定义反序列化类中重新create方法。
  def create(self, validated_data): #在views.py中校验后,save方法调用时内部会调用create。
    #在所有校验规则完毕之后,数据(validated_data是已经校验好的数据)可以直接入库
    #from . import models
    return models.User.objects.create(**validated_data)

(2)在views.py下 的User类下写post方法(对post提交的数据反序列化)

def post(self, request, *args, **kwargs):
  request_data = request.data #字典
#数据是否合法(增加对象必须是一个字典数据且有值)
  if not isinstance(request_data, dict) or not request_data:
    return Response({
      "status": 1,
"msg": "数据有误",
        })
 #数据类型合法,但数据内容不一定合法,需要校验数据,校验的(参与反序列化)数据需要赋值给data
  book_ser = serializers.UserDeserializer(data=request_data) #必须关键字data赋值
  #序列化对象调用is_valid完成校验,校验失败信息存储在序列化对象.errors中
  if book_ser.is_valid():
    book_obj = book_ser.save() #校验通过,完成新增(save的返回值就是完成校验后create返回的对象)
    return Response({
      "status": 0,
"msg": "ok",
      "results":serializers.UserSerializer(book_obj).data
      #新增和修改,都要 将反序列化的对象 再序列化 返回给其前台
       })
  else: #校验没通过(校验的错误信息存在book_ser的errors中)
    return Response({
      "status": 1,
"msg": book_ser.errors,
})

反序列化总结:

视图类中:

1)把要校验的数据交给序列化类,由data接收;

book_ser = serializers.UserDeserializer(data=request_data)

2)走is_valid校验;

if book_ser.is_valid():

3)校验成功走save方法,校验失败返回errors。

book_obj = book_ser.save()

序列化类中:

1)设置必填与选填序列化字段,设置校验规则

2)为需要额外校验的字段提供局部钩子函数,如果某些字段(如验证码)不入库且不参与全局钩子,可以将值取出pop校验(一般在全局钩子里)

3)为有联合关系的字段们提供全局钩子。如果某些字段不入库,也取出pop校验(如二次输入的密码)

4)重写create方法,完成校验通过的字段入库,得到新增的对象。

ser = 自定义序列化类(instance=模型类对象, data=empty,  **kwargs)  #序列化时传入模型类对象(instance=可以不写,直接写对象),不需要写data(data是反序列化才有);**kwargs比如当对象是个列表时,可以加个many=True参数。

ser = 自定义反序列化类(instance=None, data=数据)   #将要被反序列化的前端传来的数据传入data中。

drf之序列化组件(一):Serializer的更多相关文章

  1. Django框架(十八)—— drf:序列化组件(serializer)

    序列化组件 # 模型层 from django.db import models class Book(models.Model): nid = models.AutoField(primary_ke ...

  2. Django框架(十九)—— drf:序列化组件(serializer)

    目录 序列化组件 一.利用for循环来实现序列化(繁琐) 二.利用Django提供的序列化组件(不可控需要的字段) 三.利用drf提供的序列化组件 1.基于Serializer类实现序列化--基本语法 ...

  3. 第三章、drf框架 - 序列化组件 | Serializer

    目录 第三章.drf框架 - 序列化组件 | Serializer 序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer( ...

  4. DRF的序列化组件

    目录 DRF的序列化组件 Serializer组件 序列化 反序列化 ModelSerializer组件 序列化和反序列化 自定义Response方法 基表相关 DRF中ORM的多表关联操作 外键设计 ...

  5. drf框架 - 序列化组件 | Serializer

    序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 序列化与反序列化 序列化: 将对象序列化成字符串用户传输 ...

  6. Django框架 --序列化组件(serializer)

    一 .Django自带序列化组件 Django内置的serializers(把对象序列化成json字符串) from django.core import serializers from djang ...

  7. drf 之序列化组件

    序列化 把Python中对象转换为json格式字符串 反序列化 把json格式转为为Python对象. 用orm查回来的数据都是都是一个一个的对象, 但是前端要的是json格式字符串. 序列化两大功能 ...

  8. DRF(3) - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件

    一.序列化组件 基于上篇随笔的表结构,通过序列化组件的ModelSerializer设计如下三个接口: GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} PU ...

  9. drf框架 - 序列化组件 | ModelSerializer (查,增,删,改)

    ModelSerializer 序列化准备: 配置 settings.py # 注册rest_framework框架 INSTALLED_APPS = [ ... 'rest_framework' ] ...

随机推荐

  1. 【JVM】堆体系结构及其内存调优

    堆体系结构 一个JVM实例只存在一个堆内存,堆内存的大小是可调节的.类加载器读取类文件后,需要把类.方法.常量.变量放在堆内存中,保存所有引用类型的真实信息,以方便执行器指向,堆内存分为三个部分:年轻 ...

  2. python 反向shell后门

    linux 编码改为utf-8,windows 默认gbk,python一般都是白名单减少查杀可能性,端口可以改为443,ssl混肴数据传输. python client端 import subpro ...

  3. CSS用户自定义样式

    在浏览器中打开前面写的例子页面,你会发现 <strong> 元素中的文字会比其他文字粗一些.这些样式就是在浏览器定义的默认HTML样式. 而<strong> 元素是红色的,这是 ...

  4. 01 . 前端之HTML

    初识前端 HTML简介历史 HTML(Hyper Text Markup Language)超文本标记语言,它不同于编程语言 超文本就是超过纯文本的范畴,例如描述文本的颜色.大小.字体等信息,或使用图 ...

  5. Beta冲刺 —— 5.31

    这个作业属于哪个课程 软件工程 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.讨论并解决每个人存在的问 ...

  6. Java实现 洛谷 多项式输出

    题目描述 一元nn次多项式可用如下的表达式表示: 其中,a_ix^ia i ​ x i 称为ii次项,a_ia i ​ 称为ii次项的系数.给出一个一元多项式各项的次数和系数,请按照如下规定的格式要求 ...

  7. Java实现 LeetCode 717 1比特与2比特字符(暴力)

    717. 1比特与2比特字符 有两种特殊字符.第一种字符可以用一比特0来表示.第二种字符可以用两比特(10 或 11)来表示. 现给一个由若干比特组成的字符串.问最后一个字符是否必定为一个一比特字符. ...

  8. Java实现 洛谷 P1567 统计天数

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...

  9. PAT A+B和C

    题目描述 给定区间[-2的31次方, 2的31次方]内的3个整数A.B和C,请判断A+B是否大于C. 输入描述: 输入第1行给出正整数T(<=10),是测试用例的个数.随后给出T组测试用例,每组 ...

  10. 重学 Java 设计模式:实战桥接模式(多支付渠道「微信、支付宝」与多支付模式「刷脸、指纹」场景)

    作者:小傅哥 博客:https://bugstack.cn - 编写系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么你的代码那么多ifelse 同类的业务.同样的功能, ...