rest-framework序列化
一、创建表及手动插入数据,以便后面操作
1、创建用户组表
class UserGroupModel(models.Model): """ 创建一个用户分组的 """ title = models.CharField(max_length=100, null=False, verbose_name='用户分组')
2、创建用户角色表
class RoleModel(models.Model): """ 创建一个角色表 """ title = models.CharField(max_length=100, null=False, blank=False, verbose_name='角色名称')
3、创建用户表
class UserModel(models.Model): """ 创建一个用户表 """ user_type_choices = ( (1, '普通用户'), (2, 'VIP用户') ) user_type = models.IntegerField(choices=user_type_choices, null=False, verbose_name='用户类型') # 外键关联到用户分组表 group = models.ForeignKey('UserGroupModel', on_delete=models.CASCADE) # 用户表与角色表进行多对多的关联 roles = models.ManyToManyField('RoleModel') username = models.CharField(max_length=100, null=False, verbose_name='用户名') password = models.CharField(max_length=100, null=False, verbose_name='密码')
4、创建
token
表class UserTokenModel(models.Model): """ 创建一个用户token表 """ user = models.OneToOneField(to='UserModel', on_delete=models.CASCADE) token = models.CharField(max_length=100, verbose_name='用户token')
二、不使用rest-framework
序列化返回json
数据
1、返回的是字符
from django.shortcuts import HttpResponse from django.http import JsonResponse from rest_framework.views import APIView import json from app01 import models class RoleView1(APIView): """ 使用原始的方式返回字符 """ def get(self, request, *args, **kwargs): role = models.RoleModel.objects.all().values('id', 'title') role = list(role) ret = json.dumps(role, ensure_ascii=False) return HttpResponse(ret)
三、官网这个地方分三个来章节来介绍
四、使用rest-framework
序列化
- 1、在
app
包下创建一个文件serializers.py
2、导包
from rest_framework import serializers
3、新增一个序列化的类
class RolesSerializer(serializers.Serializer): """ 序列化角色表 """ title = serializers.CharField()
4、在视图类中使用序列化类
class RoleView2(APIView): """ 使用rest-framework序列化返回数据 """ def get(self, request, *args, **kwargs): role = models.RoleModel.objects.all() # many=True表示返回多条数据(一般列表写many=True,对象就写many=False) ser = RolesSerializer(instance=role, many=True) # 直接使用序列化后的.data ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
5、返回对象
from app01.serializer import RolesSerializer class RoleView2(APIView): """ 使用rest-framework序列化返回数据 """ def get(self, request, *args, **kwargs): role = models.RoleModel.objects.all().first() ser = RolesSerializer(instance=role, many=False) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
6、总结:
- 1、在项目开发过程中一般会把
serializer
与视图类分开不同文件来写,通过导包的方式导入 - 2、
serializer
也可以做分发功能(文件明了)
- 1、在项目开发过程中一般会把
五、序列化常见的字段
1、源码中拷贝出来的
serializer_field_mapping = { # 对应model中的字段:serializer对应的字段 models.AutoField: IntegerField, models.BigIntegerField: IntegerField, models.BooleanField: BooleanField, models.CharField: CharField, models.CommaSeparatedIntegerField: CharField, models.DateField: DateField, models.DateTimeField: DateTimeField, models.DecimalField: DecimalField, models.EmailField: EmailField, models.Field: ModelField, models.FileField: FileField, models.FloatField: FloatField, models.ImageField: ImageField, models.IntegerField: IntegerField, models.NullBooleanField: NullBooleanField, models.PositiveIntegerField: IntegerField, models.PositiveSmallIntegerField: IntegerField, models.SlugField: SlugField, models.SmallIntegerField: IntegerField, models.TextField: CharField, models.TimeField: TimeField, models.URLField: URLField, models.GenericIPAddressField: IPAddressField, models.FilePathField: FilePathField, }
六、关于source
的使用
将用于填充字段的属性的名称。可以是一个只接受
self
参数的方法,如URLField(source='get_absolute_url')
,或者使用点符号来遍历属性,如EmailField(source='user.email')
1、序列化用户表
class UserSerializer(serializers.Serializer): id = serializers.IntegerField() user_type = serializers.CharField() username = serializers.CharField() password = serializers.CharField() class UserView1(APIView): def get(self, request, *args, **kwargs): user = models.UserModel.objects.all() ser = UserSerializer(instance=user, many=True) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
2、返回结果
[{"id": 1, "user_type": "1", "username": "hello", "password": "123"}, {"id": 2, "user_type": "2", "username": "word", "password": "123"}, {"id": 3, "user_type": "1", "username": "hehe", "password": "123"}]
3、我们要把
user_type
显示出中文字出来class UserSerializer(serializers.Serializer): id = serializers.IntegerField() # 会调用row.user_type字段 xx = serializers.CharField(source="user_type") # source会调用row.get_user_type_display()方法 yy = serializers.CharField(source="get_user_type_display") username = serializers.CharField() password = serializers.CharField() class UserView1(APIView): def get(self, request, *args, **kwargs): user = models.UserModel.objects.all() ser = UserSerializer(instance=user, many=True) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
4、返回数据
[{"id": 1, "xx": "1", "yy": "普通用户", "username": "hello", "password": "123"}, {"id": 2, "xx": "2", "yy": "VIP用户", "username": "word", "password": "123"}, {"id": 3, "xx": "1", "yy": "普通用户", "username": "hehe", "password": "123"}]
七、显示外键的值
class UserSerializer(serializers.Serializer):
id = serializers.IntegerField()
xx = serializers.CharField(source="user_type")
yy = serializers.CharField(source="get_user_type_display")
username = serializers.CharField()
password = serializers.CharField()
# 通过.的方式获取外键的值
gp = serializers.CharField(source='group.title')
class UserView1(APIView):
def get(self, request, *args, **kwargs):
user = models.UserModel.objects.all()
ser = UserSerializer(instance=user, many=True)
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
八、多对多的字段显示
class UserSerializer(serializers.Serializer):
id = serializers.IntegerField()
xx = serializers.CharField(source="user_type")
yy = serializers.CharField(source="get_user_type_display")
username = serializers.CharField()
password = serializers.CharField()
gp = serializers.CharField(source='group.title')
# 使用自定义字段来显示role
role = serializers.SerializerMethodField()
def get_role(self, row):
"""
定义一个函数来获取role(get_自定义字段名)
:param row:
:return:
"""
# 根据row获取全部的角色
role_all = row.roles.all()
ret = []
for item in role_all:
ret.append({'id': item.id, 'title': item.title})
return ret
九、使用ModelSerializer
直接返回字段
1、将数据库表中字段全部返回
# 注意这个地方要继承serializers.ModelSerializer class UserSerializer(serializers.ModelSerializer): class Meta(object): model = models.UserModel # 使用__all__表示返回表中全部的字段 fields = '__all__' class UserView1(APIView): def get(self, request, *args, **kwargs): user = models.UserModel.objects.all() ser = UserSerializer(instance=user, many=True) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
2、返回部分字段
class UserSerializer(serializers.ModelSerializer): class Meta(object): model = models.UserModel # fields = '__all__' # 定义要返回的字段 fields = ['id', 'username', 'password', 'roles'] class UserView1(APIView): def get(self, request, *args, **kwargs): user = models.UserModel.objects.all() ser = UserSerializer(instance=user, many=True) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
3、结合上面自定义字段
class UserSerializer(serializers.ModelSerializer): yy = serializers.CharField(source="get_user_type_display") gp = serializers.CharField(source='group.title') # 使用自定义字段来显示role role = serializers.SerializerMethodField() class Meta(object): model = models.UserModel fields = ['id', 'username', 'password', 'yy', 'gp', 'role'] def get_role(self, row): """ 定义一个函数来获取role(get_自定义字段名) :param row: :return: """ # 根据row获取全部的角色 role_all = row.roles.all() ret = [] for item in role_all: ret.append({'id': item.id, 'title': item.title}) return ret class UserView1(APIView): def get(self, request, *args, **kwargs): user = models.UserModel.objects.all() ser = UserSerializer(instance=user, many=True) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
十、深度查找
在上面我们介绍了使用
source
或者使用自定义字段来显示关联表的数据,其实在项目中开发也可以使用深度查找,简化代码量
1、演示代码
class UserSerializer(serializers.ModelSerializer): class Meta(object): model = models.UserModel fields = '__all__' depth = 1
2、关于深度查找的认识
- 1.深度查找是查找关于一对多,多对多的关系中使用到,用来查找关于外键相关联起来的字段
- 2.深入查找的建议是1-10层,每一层就表示一个关系表的约束
十一、序列化生成hypermedialink
(url
模式,常见图片地址)
1、定义一个分组的视图类
from django.shortcuts import HttpResponse from rest_framework.views import APIView from rest_framework import serializers import json from app01 import models class GroupSerializer(serializers.ModelSerializer): class Meta(object): model = models.UserGroupModel fields = '__all__' class GroupView(APIView): def get(self, request, *args, **kwargs): id = kwargs.get('id') obj = models.UserGroupModel.objects.filter(id=id).first() ser = GroupSerializer(instance=obj, many=False) res = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(res)
2、定义分组的
url
地址urlpatterns = [ path('group/<int:id>/', group.GroupView.as_view(), name="gp"), ]
3、序列化用户表
class UserSerializer1(serializers.ModelSerializer): # 注意这个地方的lookup_url_kwarg要和配置url地址处的相同 group = serializers.HyperlinkedIdentityField(view_name='gp', lookup_field='group_id', lookup_url_kwarg='id') class Meta(object): model = models.UserModel fields = ['id', 'username', 'password', 'group', 'roles'] depth = 1 class UserView1(APIView): def get(self, request, *args, **kwargs): user = models.UserModel.objects.all() # 注意如果这个地方使用了hypermedialink就要写上context={'request': request} ser = UserSerializer1(instance=user, many=True, context={'request': request}) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
4、返回数据
[ { "id": 1, "username": "hello", "password": "123", "group": "http://127.0.0.1:9000/app01/api/v1/group/1/", "roles": [ { "id": 1, "title": "员工" }, { "id": 2, "title": "经理" } ] } ]
十二、验证用户输入数据(类似前面的form
)
1、定义序列化的
class GroupSerializer1(serializers.Serializer): title = serializers.CharField(required=True, error_messages={'required': '必填字段'})
2、在视图类中使用
class GroupView(APIView): def get(self, request, *args, **kwargs): id = kwargs.get('id') obj = models.UserGroupModel.objects.filter(id=id).first() ser = GroupSerializer(instance=obj, many=False) res = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(res) def post(self, request, *args, **kwargs): # 配置就解析器才可以这样取值 ser = GroupSerializer1(data=request.data) if ser.is_valid(): print(ser.validated_data) else: print(ser.errors) return HttpResponse('提交数据')
十三、使用序列化的综合案例
- 1、总要功能,在序列化中定义创建的函数,然后使用
post
方式创建数据 2、序列化数据
from rest_framework import serializers from app01 import models class RolesSerializer(serializers.Serializer): id = serializers.IntegerField(required=False) title = serializers.CharField(required=True, max_length=100) def create(self, validated_data): """ 创建新增数据的时候 :param validated_data: :return: """ return models.RoleModel.objects.create(**validated_data)
3、在视图中定义
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from app01 import models from app01.serializers import roles class RoleView(APIView): def get(self, request, *args, **kwargs): """ 定义获取数据的视图 """ roles_all = models.RoleModel.objects.all() ser = roles.RolesSerializer(instance=roles_all, many=True) return Response(ser.data) def post(self, request, *args, **kwargs): """ 定义创建数据的视图,如果校验成功就添加到数据库,否则就返回错误 """ serializer = roles.RolesSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_401_UNAUTHORIZED)
4、视图中定义
from django.urls import path from app01.views import roles urlpatterns = [ path('roles/', roles.RoleView.as_view()) ]
十四、总结
- 1、如果是一对多的关系表(外键关联)就要使用
source
- 2、如果是多对多的关系表就要使用
SerializerMethodField