首先介绍一下相关概念

序列化器(Serializer)

  1. 自定义型:  继承rest_framework.serializers.Serializer

  2. 模型类型:  继承rest_framework.serializers.ModelSerializer

创建Serializer对象

构造方法:Serializer(instance=None, data=empty, **kwarg)

参数1,序列化必须传入的模型类对象

参数2,反序列化时把数据传入data

额外参数:例如context={'XX':'XX'},可通过context属性获取, context上下文解析详解上面官方文档

序列化注意点:

1. 序列化时如果被序列化是多条查询集,通过添加many=True,列表形式

如果关联对象有多个,也可以在序列化器字段添加many=True

2. 如果模型类存在外键字段,处理方式如下:

①PrimaryKeyRelatedField,需设置read_only=True或queryser参数

被序列化后是关联字段数据

②StringRelatedField,被序列化是关联对象__str__返回值

③HyperlinkedRelatedField,需设置read_only,view_name

被序列化为关联对象数据的API链接

④SlugRelateField,需设置read_only,slug_field

被序列化后是关联对象的指定字段数据

⑤使用关联对象的序列化器类的实例

⑥重写to_representation 可修改被序列化后的返回值

反序列化

验证:在反序列化时,对数据验证,验证成功后才可获取数据或保存为模型类对象

①调用is_valid方法验证,成功True,失败False

②验证失败时,通过序列化器对象的errors属性获取错误信息,返回字典包含字段和字段错误,如果非字段错误,可修改配置中NON_FIELD_ERRORS_KEY来控制键名

③验证成功时,通过序列化器对象的validated_date属性获取数据

注意点:带参数raise_exception=True在反序列化时is_valid()方法在验证失败时抛出serializers.ValidationError,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。

自定义验证行为:

1. validate_字段名:在序列化器中添加方法,方法名validate_字段名,参数为value,对value做校验,raise

serializers.ValidationError('XXXX'),返回值value

2. validate:在序列化器中添加validate方法,可同时对多个字段进行验证

参数为attrs,从attrs中获取值,然后进行逻辑处理,抛出异常,返回值attrs

3.validator:在序列化器上方编写函数,参数value,对value校验,抛出异常

在序列化器字段中加入validator选项参数,为列表形式,值为函数名。

4.REST framework提供的validators:

UniqueValidator单字段唯一:字段中设置,参数为queryset

UniqueTogetherValidation联合唯一:class Meta中设置,参数queryset和fields

保存:如果验证成功,向基于validated_data完成数据对象的创建,可以通过create和update来实现

1.新建:在序列化器中重写create方法,参数为validate_data,

返回值为模型类.objects.create(**validated_data)

2.更新:在序列化器中重写update方法,参数instance即要更新的实例和validate_data

对validate_data字典获取其值,对无传递值给予默认值 instance.字段,并赋给instance.字段,然后调用instance.save()提交,返回值instance

注意点:

①实现了create和update方法后,在反序列化时既可以序列化对象.save()返回数据对象实例并保存或更新到数据库

②调用save时,如果有传instance实例,则调用update方法更新数据,否则调用create方法新建数据。

③调用save可传参,参数可从validated_data中获取

④如果没有传递所有required字段,会抛出验证异常,可通过使用partial=True实现部分字段更新

模型类序列化器ModelSerializer

可基于模型类自动生成一系列字段,会自动生成valiators和实现了默认的create和update方法

ModelSerializer

ModelSerializer 类似于 ModelForm 提供了一些便捷的方法,使你可以自动对 Django Model 中包含的部分或所有字段序列化。
用法上 ModelSerializer 和 Serializer 基本相同,除下面几点外:

    • 在 Model 字段的基础上自动生成序列化字段
    • 自动生成对 unique_together 的 validators
    • 自动包含基础的 .create(), update() 的实现

关于序列化,之前在处理分页时已经使用过了。

这次通过一个用户信息列表及新增用户介绍一下ModelSerializer 在项目中的具体应用。

其他项目配置相关不做介绍,从创建models开始

# models.py

from django.db import models

# Create your models here.

class UserInfo(models.Model):
'''用户信息表''' # unique=True 限定唯一
username = models.CharField(verbose_name='用户名',max_length=32,unique=True)
# 表单提交可为空,数据库存储可为 NULL blank=True, null=True
nickname = models.CharField(verbose_name='名称', max_length=32,blank=True, null=True)
telephone = models.CharField(max_length=11, blank=True, null=True, unique=True, verbose_name='手机号码')
email = models.EmailField(max_length=64,blank=True, null=True, unique=True,verbose_name='email')
password = models.CharField(verbose_name='密码', max_length=128)
# 用户项目分组
usergroup = models.CharField(verbose_name='用户分组', max_length=128, null=True,blank=True)
# 用户类型
usertype = models.CharField(verbose_name='用户类型', max_length=128, null=True,blank=True)
avatar = models.ImageField(verbose_name='头像', upload_to='avatar', default="/avatar/default.png", null=True,blank=True)
status = models.IntegerField(verbose_name='用户状态',default=1)
userPermissions = models.CharField(verbose_name='用户权限',max_length=1024,null=True,blank=True)
createTime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
updateTime = models.DateTimeField(verbose_name='修改时间',auto_now=True)
description = models.TextField(verbose_name='备注',null=True,blank=True) class Meta:
db_table = 'UserInfo'
verbose_name = '用户信息'
verbose_name_plural = verbose_name def __str__(self):
return self.username

在项目下创建序列化文件serializers.py 代码如下

注意:注意注释说明,fields、exclude 限定那些字段,那些字段将会被实例化或是不被实例化,如exclude = ('password',),添加用户时,password 会被存储为空。

# FileName : serializers.py
# Author : Adil
# DateTime : 2019/8/20 4:58 PM
# SoftWare : PyCharm # ~/AutomatedTest/TestPlatform/serializers.py from TestPlatform.models import UserInfo from rest_framework import serializers class UserInfoSerializer(serializers.ModelSerializer): class Meta:
model = UserInfo
fields = '__all__' # fields 属性设置为特殊值 '__all__',以指示应该使用模型中的所有字段。 实例化时将可以看到所有字段
# exclude = ('password',) # 注意:结尾的 ',' 逗号,去掉会序列化失败。exclude 属性设置为从序列化程序中排除的字段列表。 实例化时将看不到 password 字段,及password 不被序列化,
# fields = ('username','password','email') # 序列化指定字段。
# exclude = ['password'] # 使用list 形式也是可以的,此时可以不要逗号。同理fields 也支持 list 形式,因为官网 就是 list形式。 # 本身ModelSerializer 它包含 .create() 和 .update() 的简单默认实现。 所以 这里 写不写 下面两个方法都行,但是在嵌套序列化 的情况下要 重写下面两个方法。
# def create(self, validated_data):
# print("~~~~~~~~~~~~~~")
# print(validated_data)
# return UserInfo.objects.create(**validated_data)
#
#
# def update(self, instance, validated_data):
#
# instance.name = validated_data.get('name',instance.name)
#
#
# instance.save()
# return instance

创建用户视图文件

# FileName : userviews.py
# Author : Adil
# DateTime : 2019/8/20 4:47 PM
# SoftWare : PyCharm # 在应用下添加用户中心文件夹usercenter,并创建用户视图文件userviews.py
# TestPlatform/usercenter/userviews.py from rest_framework.views import APIView
from django.http import JsonResponse
from rest_framework.request import Request
from TestPlatform.models import UserInfo
from TestPlatform.serializers import UserInfoSerializer class AddUserView(APIView):
'''添加用户''' def post(self,request): ret = {'code':1,'msg':None,'data':None} try: username = request.data.get('username',None) print(username) user_list = UserInfo.objects.all()
# 序列化实例
ul = UserInfoSerializer(user_list,many=True) # 虽然是单个实例对象,many = True 还是要加的,不加报错。 print(ul) print(ul.data) # 根据接口提供参数 进行反序列化
ul1 = UserInfoSerializer(data=request.data)
print("******")
print(ul1)
print(ul1.is_valid())
# 进行数据校验,通过返回True,失败返回False
if ul1.is_valid(): print(ul1.validated_data)
# 成功说明可以保存,调用 .save()保存实例到数据库。
ul1.save()
ret['msg'] = '成功!'
ret['data'] = ul1.data
# return JsonResponse(ul1.data) else:
ret['msg'] = '失败!'
# 失败返回失败信息。
ret['data'] = ul1.errors except Exception as e:
ret['code'] = 0
ret['msg'] = '失败!' return JsonResponse(ret)

配置应用下urls.py文件

# FileName : urls.py
# Author : Adil
# DateTime : 2019/8/19 4:48 PM
# SoftWare : PyCharm # TestPlatform/urls.py from django.urls import path from TestPlatform.usercenter.userviews import AddUserView urlpatterns = [ # path('add/',add)
path('adduser/',AddUserView.as_view()) ]

配置项目下主urls.py文件

# AutomatedTest/urls.py

from django.contrib import admin
from django.urls import path,include # from django.conf.urls import url,include urlpatterns = [
path('admin/', admin.site.urls),
path('auto/',include('TestPlatform.urls'))

注意:这样配置的接口路径为 auto/adduser/

启动项目,

添加用户,如图,添加了几个必填字段

添加重复用户,查看提示信息

查看数据库表

使用Serializer实现简单的增删改

urls.py文件

from django.conf.urls import url
from app01 import views urlpatterns = [
url(r'^books/', views.BookListView.as_view()), #获取多条数据和添加数据
url(r'^book/(\d+)/', views.BookView.as_view()), #获取单条数据,编辑和删除数据
]

获取多条数据和添加数据

serializer.py文件

from rest_framework import serializers
from app01 import models class AuthorSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField() class PublisherSerializer(serializers.Serializer):
name = serializers.CharField() class BookSerializer(serializers.Serializer):
title = serializers.CharField()
price = serializers.DecimalField(max_digits=6, decimal_places=2)
pub_date = serializers.DateTimeField()
pub = PublisherSerializer(read_only=True) #GET请求时需要的数据设置为只读,POST时可为空
authors = serializers.SerializerMethodField(read_only=True)
post_pub = serializers.IntegerField(write_only=True) #POST和PUT时的数据只写,GET时可为空
post_authors = serializers.ListField(write_only=True) def get_authors(self, obj):
data_obj = AuthorSerializer(obj.authors.all(), many=True) #多个对象需要many为True
return data_obj.data def create(self, validated_data): #create方法用于添加数据,validated_data校验完的数据
book_obj = models.Book.objects.create(
title=validated_data.get('title'),
price=validated_data.get('price'),
pub_date=validated_data.get('pub_date'),
pub_id=validated_data.get('post_pub'),
)
book_obj.authors.set(validated_data.get('post_authors'))
return book_obj # 将book对象返回

view.py文件

from app01.serializer import BookSerializer
class BookListView(APIView):
def get(self, request, *args, **kwargs):
all_books = models.Book.objects.all()
obj = BookSerializer(all_books,many=True)
return Response(obj.data) def post(self,request,*args,**kwargs):
print(request.data)
obj = BookSerializer(data=request.data)
if obj.is_valid(): #对数据进行校验,貌似序列化器里的多对多不会校验
obj.save() #会去序列化器里找create()方法
return Response(obj.data) #校验成功返回添加的数据
return Response({'error': obj.errors}) #校验失败返回错误信息

POST的数据

{
"title": "葵花宝典续集",
"price": "65.50",
"pub_date": "2019-07-25T07:17:09Z",
"post_pub": 1,
"post_authors": [
1
]
}

返回的数据

{
"title": "葵花宝典续集",
"price": "65.50",
"pub_date": "2019-07-25T07:17:09Z",
"pub": {
"name": "沙和尚出版社"
},
"authors": [
{
"id": 1,
"name": "沙和尚"
}
]
}

获取单条数据、编辑和修改

serializer.py文件

serializer.py文件

class BookSerializer(serializers.Serializer):
title = serializers.CharField()
price = serializers.DecimalField(max_digits=6, decimal_places=2)
pub_date = serializers.DateTimeField()
pub = PublisherSerializer(read_only=True)
authors = serializers.SerializerMethodField(read_only=True)
post_pub = serializers.IntegerField(write_only=True)
post_authors = serializers.ListField(write_only=True) def get_authors(self, obj):
data_obj = AuthorSerializer(obj.authors.all(), many=True)
return data_obj.data def create(self, validated_data): # validated_data校验完的数据
book_obj = models.Book.objects.create(
title=validated_data.get('title'),
price=validated_data.get('price'),
pub_date=validated_data.get('pub_date'),
pub_id=validated_data.get('post_pub'),
)
book_obj.authors.set(validated_data.get('post_authors'))
return book_obj # 将book对象返回 def update(self, instance, validated_data): # 修改数据时调用update方法,instance当前要求改的数据对象
instance.title = validated_data.get('title', instance.title)
instance.price = validated_data.get('price', instance.price)
instance.pub_date = validated_data.get('pub_date', instance.pub_date)
instance.pub_id = validated_data.get('post_pub', instance.pub_id)
instance.save()
instance.authors.set(validated_data.get('post_authors',instance.authors.all()))
return instance #返回修改后的数据对象

view.py文件

class BookView(APIView):
def get(self, request,pk, *args, **kwargs):
book = models.Book.objects.filter(pk=pk).first()
obj = BookSerializer(book)
return Response(obj.data) def put(self,request,pk,*args,**kwargs): #修改资源
book = models.Book.objects.filter(pk=pk).first()
obj = BookSerializer(data=request.data,instance=book,partial=True) #partial为True表示可以只传修改的那部分值
if obj.is_valid():
obj.save() #保存时会调用序列化器定义好的update()方法
return Response(obj.data) #校验成功返回修改后的对象
return Response(obj.errors) def delete(self,request,pk,*args,**kwargs): #删除资源
book = models.Book.objects.filter(pk=pk).first()
if book:
book.delete()
return Response({'info':'删除成功'})
return Response({'info': '数据不存在'})

PUT的数据

  "title": "葵花宝典1",
"price": "63.50",
"pub_date": "2019-07-25T07:17:09Z",
"post_pub": 1,
"post_authors": [
1
]
} #也可只穿修改的值
{
"title": "葵花宝典1" #注:只有一个元素,不要加逗号,不然校验不通过
}

返回的数据

{
"title": "葵花宝典1",
"price": "63.50",
"pub_date": "2019-07-25T07:17:09Z",
"pub": {
"name": "沙和尚出版社"
},
"authors": [
{
"id": 1,
"name": "沙和尚"
}
]
}

修改用户信息实例

如图修改用户信息

view视图文件

    @action(methods=['put'],detail=False)
def deluser(self,request):
'''
用户删除
:param request:
:return:
''' print("#####")
print(request)
print(request.data)
usr = request.data.get('username')
print(usr)
obj = UserInfo.objects.filter(username=usr).first()
print(obj)
# UserInfo.objects.update_or_create(username=obj,defaults={'nickname': usr}) # UserInfo.objects.update_or_create(username=obj, defaults={'nickname': usr}) ul1 = UserInfoSerializer(data=request.data, instance=obj) print(ul1.is_valid()) # print(ul1.data)
ul1.save() print("return") print() return Response({'code': 1, 'msg': 'success', 'errors': {}}) def put(self, request, *args, **kwargs):
print("#####")
print(request)
print(request.data)
usr = request.data.get('username')
print(usr)
obj = UserInfo.objects.filter(username=usr).first()
print(obj)
# UserInfo.objects.update_or_create(username=obj,defaults={'nickname': usr}) # UserInfo.objects.update_or_create(username=obj, defaults={'nickname': usr}) ul1 = UserInfoSerializer(data=request.data,instance=obj) print(ul1.is_valid()) # print(ul1.data)
ul1.save() print("return") print() return Response({'code':1,'msg':'success','errors':{}})

以上提供两种写法进行put请求

postman请求如下

方式1:

结果如下:

方式2:

结果如下:

先简单介绍到这里,后续介绍一下,接口请求等相关知识。

Django restframework 序列化之 ModelSerializer 小记的更多相关文章

  1. python Django rest-framework 序列化步骤

    django-rest-framework,是一套基于Django 的 REST 框架,是一个强大灵活的构建 Web API 的工具包.本文介绍一下 django-rest-framework 的简单 ...

  2. django restframework 序列化

    Serialization 序列化 创建表 from django.db import models from pygments.lexers import get_all_lexers from p ...

  3. python Django rest-framework 创建序列化工程步骤

    11创建项目 2创建应用 3stting添加应用(apps)-添加制定数据库-修改显示汉字(zh-hans)-上海时区(Asia/Shanghai) 4主路由添加子路由 5应用里创建子路由 6创建数据 ...

  4. 从django的序列化到rest-framework 序列化

    1.利用Django的view实现返回json数据 from django.views.generic import View from goods.models import Goods class ...

  5. django restframework serializer 增加自定义字段

    在使用django restframework serializer 序列化在django中定义的model时,有时候我们需要额外在serializer中增加一些model中没有的字段.有两种方法实现 ...

  6. rest-framework序列化

    快速实例 Quickstart 序列化 开篇介绍: ---- 一切皆是资源,操作只是请求方式 ----book表增删改查 /books/ books /books/add/ addbook /book ...

  7. Django Restframework 实践(一)

    具备以下知识: django http://www.cnblogs.com/menkeyi/p/5882464.html http://www.cnblogs.com/menkeyi/p/588245 ...

  8. django restframework 的日常使用

    本文讨论 django restframework 的日常使用,满足常用 api 编写的需求,比如 List, Detail, Update, Put, Patch 等等.探讨 django rest ...

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

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

随机推荐

  1. firewalld基础

    firewalld是一个基于网络区域的动态管理防火墙的守护进程.在iptables中需要理解表,链等概念,而在firewalld中需要从理解区域的概念开始 防火墙依照特定的规则允许或限制输出的数据通过 ...

  2. linux 安装PostgreSQL12

    一.安装步骤 1.设置保存安装包的目录 # cd /usr/local/src 2.开始下载源包 # wget https://ftp.postgresql.org/pub/source/v12.1/ ...

  3. HttpContext.Current.Server.MapPath("") 未将对象设置到引用的

    在多线程中使用该方法获取目录报错:未将对象设置到引用 #region 上传图片到腾讯 public async Task<Result> UploadImageToWX(string ba ...

  4. 13. 抽象类 & 接口

    一.抽象类 // 抽象类Shape public abstract class Shape { // 1. 成员变量 private String color; // 2. 初始化块 { System ...

  5. Appium自动化WebView中元素的操作

    在App开发过程中,很容易用到第三方的WebView控件,这个属于移动端混合型App.在我们做自动化测试的过程中,就要对这种情况进行处理,最通用的办法就是先将appium切换到webview模式然后按 ...

  6. imutils.path

    from imutils import paths # 要在哪条路径下查找 path = '...' # 查找图片,得到图片路径 imagePaths = list(imutils.paths.lis ...

  7. 第三方系统平台如何对接gooflow2.0

    第一步,参与者数据源配置 目前提供3种参与者数据源(员工,角色,部门),还有一种sql语句 XML配置如下 <?xml version="1.0" encoding=&quo ...

  8. windows/tomcat 修改java虚拟机JVM以utf-8字符集加载class文件的两种方式

      1.情景展示 做了这么长时间的java开发,但是,你知道JVM是以怎样的编码加载.解析class文件的吗? 我们知道,通常情况下,我们会将java文件的字符集修改成utf-8,这样,理所当然地就认 ...

  9. Mac流程图的软件

    里面有破解机器,按照步骤一步步来就可以了 https://www.zhinin.com/omnigraffle_pro-mac.html

  10. torch_10_stackGAN-V2

    核心要点 StackGAN旨在生成高分辨率的真实图片. stackGAN-v1架构包含两个阶段:用于文本到图像的合成,阶段1GAN根据给定的文本描述绘制对象的形状和颜色,生成低分辨率图像.阶段2将阶段 ...