rest framework 之序列化
一、示例
restful work 的序列号就类似于 Django 的 Form 表单。
1、api/urls.py
from django.urls import path, re_path
from api.views import UserView, ParserView, RolesView
urlpatterns = [
# path('users/', UserView.as_view()),
re_path('(?P<version>[v1|v2]+)/users/', UserView.as_view(), name='api_user'), # 解析
re_path('(?P<version>[v1|v2]+)/roles', RolesView.as_view()), # 序列化
path('parser/', ParserView.as_view(), name='api_parer'),
]
api/views.py
from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from rest_framework import serializers
from app import models
import json
class RolesSerializers(serializers.Serializer):
"""序列化类(对应 Role 模型类中字段)"""
id = serializers.IntegerField()
name = serializers.CharField()
class RolesView(APIView):
def get(self, request, *args, **kwargs):
# 取出全部
# roles = models.Role.objects.all()
# # 序列化,两个参数,instance:接受Queryset(或者对象) mangy=True表示处理多个对象,mant=False表示处理单个对象
# ser = RolesSerializers(instance=roles, many=True)
# # 转成json格式,ensure_ascii=False表示显示中文,默认为True
# ret = json.dumps(ser.data, ensure_ascii=False)
# 取出第一个
role = models.Role.objects.all().first()
ser = RolesSerializers(instance=role, many=False)
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
app/models.py
from django.db import models
class UserInfo(models.Model):
USER_TYPE = (
(1, '普通用户'),
(2, 'VIP'),
(3, 'SVIP')
)
user_type = models.IntegerField(choices=USER_TYPE)
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
group = models.ForeignKey('UserGroup', on_delete=models.CASCADE, verbose_name='所属组', null=True, blank=True)
roles = models.ManyToManyField('Role', verbose_name='角色')
class UserToken(models.Model):
user = models.OneToOneField(UserInfo, on_delete=models.CASCADE)
token = models.CharField(max_length=64)
class UserGroup(models.Model):
"""分组"""
name = models.CharField(verbose_name='组名', max_length=64)
class Role(models.Model):
"""角色"""
name = models.CharField(max_length=64, verbose_name='角色名')
- 访问:
http://127.0.0.1:8000/api/v1/roles
{"id": 1, "name": "老板"}
二、进阶
前面我们只序列化了没有关联的字段,对于多选字段、外键以及多对多字段都没有演示,在这里我们还将学习如何自定义一个序列化方法。
1、各个数据表数据:
2、api/urls.py
from django.urls import path, re_path
from api.views import UserView, ParserView, RolesView, UserInfoView
urlpatterns = [
# path('users/', UserView.as_view()),
re_path('(?P<version>[v1|v2]+)/users/', UserView.as_view(), name='api_user'),
re_path('(?P<version>[v1|v2]+)/roles', RolesView.as_view()), # 序列化
re_path('(?P<version>[v1|v2]+)/info', UserInfoView.as_view()), # 序列化
path('parser/', ParserView.as_view(), name='api_parer'),
]
3、api/views.py
class UserInfoSerializers(serializers.Serializer):
# 多选字段:user_type是choices(1,2,3),显示全称的方法用 get_字段名_display
type = serializers.CharField(source='get_user_type_display')
username = serializers.CharField()
password = serializers.CharField()
# 外键字段: group.name:组的名字
group = serializers.CharField(source="group.name")
# SerializerMethodField(),表示自定义显示
# 然后写一个自定义的方法
rls = serializers.SerializerMethodField()
def get_rls(self, row):
"""获取用户所有角色,get_rls 和上面自定义方法名字一致"""
print(row) # UserInfo object (2)
role_obj_list = row.roles.all()
print(role_obj_list) # <QuerySet [<Role: Role object (1)>]>
ret = []
# 获取角色的id和名字
# 以字典的键值对方式显示
for item in role_obj_list:
ret.append({"id": item.id, "name": item.name})
return ret
class UserInfoView(APIView):
def get(self, request, *args, **kwargs):
users = models.UserInfo.objects.all()
ser = UserInfoSerializers(instance=users, many=True)
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
- 访问:
http://127.0.0.1:8000/api/v1/info
:
[{"type": "普通用户", "username": "rose", "password": "123", "group": "一组", "rls": [{"id": 1, "name": "老板"}]}, {"type": "VIP", "username": "john", "password": "123", "group": "二组", "rls": []}, {"type": "SVIP", "username": "hj", "password": "123", "group": "三组", "rls": [{"id": 4, "name": "普通员工"}]}]
总结
- 多选字段:使用
get_字段名_display
获取字段原始值 - 外键字段:
source="外键名.要获取的字段名"
- 多对多字段:可通过自定义分实现
- 自定义方法:
mth = serializers.SerializerMethodField()
,方法名:get_mth()
三、ModelSerializer
ModelSerializer
效果类似于 Django Form 中的 ModelForm
,
class UserInfoSerializers(serializers.ModelSerializer):
type = serializers.CharField
group = serializers.CharField(source="group.name")
rls = serializers.SerializerMethodField()
def get_rls(self, row):
pass
class Meta:
model = models.UserInfo
# fields = '__all__'
fields = ['id','username','password','type','group','rls']
四、depth 控制连表的深度
当表与表之间多个相连,如果只想显示前面几层,可以使用 depth
控制连表的深度:
class UserInfoSerializers(serializers.ModelSerializer):
type = serializers.CharField
group = serializers.CharField(source="group.name")
rls = serializers.SerializerMethodField()
def get_rls(self, row):
pass
class Meta:
model = models.UserInfo
# fields = '__all__'
fields = ['id','username','password','type','group','rls']
depth = 1 # 控制为 1 层
六、HyperlinkedidentityField 生成 url
序列化关联数据表的相应字段的 url,就像下面这种:
[
{
"id": 1,
"publish": "http://127.0.0.1:8080/api/publish/1",
"name": "红楼梦",
"price": "123.00",
"publish_date": null
},
{
"id": 2,
"publish": "http://127.0.0.1:8080/api/publish/2",
"name": "西游记",
"price": "234.00",
"publish_date": null
}
]
1、api/serializers.py
from rest_framework import serializers
from app import models
class UserInfoSerializers(serializers.ModelSerializer):
"""用户个人信息序列化"""
group = serializers.HyperlinkedIdentityField(view_name='gob', lookup_field='group_id', lookup_url_kwarg='pk')
class Meta:
model = models.UserInfo
fields = '__all__'
class RolesSerializers(serializers.Serializer):
"""序列化类"""
id = serializers.IntegerField()
name = serializers.CharField()
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserGroup
fields = "__all__"
参数:
- view_name:关联路由 URL 中的 name 参数值,用来反向解析 URL
- lookup_field:要查找的目标字段,如:
group_id
是UserInfo
模型中的外键字段(即我们要查找的字段) - lookup_url_kwarg:关键字参数的名称,该参数对应于查找字段,一般为 pk
2、api/urls.py
from django.urls import path, re_path
from api.views import UserView, ParserView, RolesView, UserInfoView, GroupView
urlpatterns = [
re_path('(?P<version>[v1|v2]+)/info/', UserInfoView.as_view()), # 序列化
re_path('(?P<version>[v1|v2]+)/group/(?P<pk>\d+)/', GroupView.as_view(), name='gob'), # 序列化生成url
]
3、api/views.py
from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser
from .serializers import GroupSerializer, RolesSerializers, UserInfoSerializers
from app import models
from django.http import JsonResponse
class UserInfoView(APIView):
def get(self, request, *args, **kwargs):
users = models.UserInfo.objects.all()
# 这里必须指定 context,将 request 传递给 UserInfoSerializers
user_ser = UserInfoSerializers(instance=users, many=True, context={'request': request})
return JsonResponse(user_ser.data, safe=False)
class GroupView(APIView):
def get(self, request, *args, **kwargs):
# pk = kwargs.get('pk')
# group = models.UserGroup.objects.filter(pk=pk).first()
#
# group_ser = GroupSerializer(instance=group, many=False)
# # ret = json.dumps(ser.data, ensure_ascii=False)
# return JsonResponse(group_ser.data, safe=False)
return HttpResponse('ok')
4、访问:http://127.0.0.1:8000/api/v2/info/
[
{
"id": 1,
'username': 'rose', john/hj
'password': '123',
"group": "http://127.0.0.1:8080/api/group/1",
"roles": [
2,
]
},
{
"id": 2,
'username': 'john',
'password': '123',
"group": "http://127.0.0.1:8080/api/group/2",
"roles": [
1,
]
},
]
七、用户请求数据验证
验证用户请求的数据是否合法
1、api/serializers.py
from rest_framework import serializers
class UserGroupSerializers(serializers.Serializer):
"""用户请求验证"""
title = serializers.CharField()
2、api/views.py
from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from .serializers import GroupSerializer, RolesSerializers, UserInfoSerializers, UserGroupSerializers
class UserGroupView(APIView):
"""用户请求验证"""
def post(self, request, *args, **kwargs):
usergroup_ser = UserGroupSerializers(data=request.data)
if usergroup_ser.is_valid():
print(usergroup_ser.validated_data['title'])
else:
print(usergroup_ser.errors)
return HttpResponse('用户提交数据错误')
3、利用 postman 模拟用户请求发送数据
请求方式 post,参数格式 JSON:
当请求的数据为空时,会自动验证数据的合法性:
八、自定义验证规则
你可以自定义验证规则,比如验证用户输入的字段必须以什么开头,必须是邮箱格式等:
1、api/serializers.py
class GroupValidation:
"""自定义验证规则"""
def __init__(self, base):
self.base = base # love
def __call__(self, value, *args, **kwargs):
if not value.startswith(self.base):
msg = '标题必须以 %s 开头' % self.base
raise serializers.ValidationError(msg)
class UserGroupSerializers(serializers.Serializer):
"""用户请求数据验证"""
# title = serializers.CharField()
title = serializers.CharField(validators=[GroupValidation('love'), ])
2、其余的不变,现在验证规则按照我们设置的走,错误提示也一样:
rest framework 之序列化的更多相关文章
- Django Rest framework 之 序列化
RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...
- Django Rest Framework(2)-----序列化详解(serializers)
REST framework中的序列化类与Django的Form和ModelForm类非常相似.我们提供了一个Serializer类,它提供了一种强大的通用方法来控制响应的输出,以及一个ModelSe ...
- Django restful Framework 之序列化与反序列化
1. 首先在已建好的工程目录下新建app命名为snippets,并将snippets app以及rest_framework app加到工程目录的 INSTALLED_APPS 中去,具体如下: IN ...
- Django REST Framework的序列化器是什么?
# 转载请留言联系 用Django开发RESTful风格的API存在着很多重复的步骤.详细可见:https://www.cnblogs.com/chichung/p/9933861.html 过程往往 ...
- Django rest framework之序列化小结
最近在DRF的序列化上踩过了不少坑,特此结合官方文档记录下,方便日后查阅. [01]前言 serializers是什么?官网是这样的”Serializers allow complex d ...
- CAF(C++ actor framework)(序列化之复杂类,分析 还有自己不懂的细思恐极函数实现)(三)
这里应该是序列化的最后一篇.感觉自己写的不是很好,也一点点在学习.这次就不贴上代码了.代码在github上的announce5.cpp.代码简单,但是分析下去会有细思恐极的感觉! 先看一下几个函数是干 ...
- CAF(C++ actor framework)(序列化之结构体,任意嵌套STL)(一)
User-Defined Data Types in Messages(用户自定义类型)All user-defined types must be explicitly “announced” so ...
- django rest framework serializers序列化
serializers是将复杂的数据结构变成json或者xml这个格式的 serializers有以下几个作用: - 将queryset与model实例等进行序列化,转化成json格式,返回给用户(a ...
- django-插件django REST framework,返回序列化的数据
官网: http://www.django-rest-framework.org 1.安装 pip install djangorestframework 2.在setting.py中注册app 中添 ...
- restful framework之序列化组件
一.Django自带序列化组件 from django.core import serializers def test(request): book_list = Book.objects.all( ...
随机推荐
- Linux下进程间通信方式——信号量(Semaphore)
1.信号量 信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送数据 ...
- 使用Swagger2构建SpringMVC项目中的Restful API文档
使用Swagger自动生成API文档,不仅增加了项目的可维护性,还提高了API的透明度更利于快速测试等工作,便于更快地发现和解决问题. 本篇文章只记录整合过程,关于Security Configura ...
- suse12.2构建samba
1:添加用户 useradd wangjunhui -d /home/wangjunhuipasswd wangjunhui 2:配置samba smbpasswd -a wangjunhui vi ...
- dial tcp 10.96.0.1:443: getsockopt: no route to host --- kubernetes(k8s)DNS 服务反复重启
kubernetes(k8s)DNS 服务反复重启解决: k8s.io/dns/pkg/dns/dns.go:150: Failed to list *v1.Service: Get https:// ...
- 《Linux就该这么学》培训笔记_ch01_部署虚拟环境安装Linux系统
<Linux就该这么学>培训笔记_ch01_部署虚拟环境安装Linux系统 文章最后会post上书本的笔记照片. 文章主要内容: 在虚拟机中安装红帽RHEL7系统 在Linux系统中找回r ...
- SpringBootSecurity学习(18)前后端分离版之 OAuth2.0 数据库(MyBatis)存储客户端
使用Mybatis查询客户端信息 前面的例子使用了默认的jdbc配置来动态从数据库查询客户端信息,下面来改用更加灵活的mybatis来实现,改用mybatis,首先pom中换成mybatis的依赖: ...
- spring Boot 学习(六、Spring Boot与分布式)
一.分布式应用在分布式系统中,国内常用zookeeper+dubbo组合,而Spring Boot推荐使用 全栈的Spring,Spring Boot+Spring Cloud 分布式系统: 单一应用 ...
- C# VB .net读取识别条形码线性条码codabar
codabar是比较常见的条形码编码规则类型的一种.如何在C#,vb等.NET平台语言里实现快速准确读取codabar条形码呢?答案是使用SharpBarcode! SharpBarcode是C#快速 ...
- vuejs应用开发前后端分离
我们知道,无论是web应用还是app应用都有一个前后端,前端主要负责界面交互,后端负责数据持久化.在正规公司中一般是由两个团队来分别完成前端和后端的开发,在小公司或者个人开发的项目中,前后端很有可能是 ...
- 正则表达式回溯导致的CPU打满
参考: https://my.oschina.net/ttscjr/blog/2208526 https://mp.weixin.qq.com/s?__biz=MzA4MjIyNTY0MQ==& ...