目录
一、Django内置的serializers模块 - 将对象序列化
1-1 单表操作(单表的get获取以及数据化)
二、DRF框架 - Serializer 组件
2-1 单表操作
2-1-1 缺少 safe=False 的错误信息 - 防止序列化的字典内套了列表
2-2 多表操作
2-2-1 models结构
2-2-2 View视图函数
2-2-3 serializers 自定义类 - 等待view视图函数对象的传入,以及对象处理的逻辑
三、DRF框架 - ModelSerializer组件
四、DRF - HyperlinkedIdentityField组件 - 用于链接的拼接
五、DRF - 反序列化
5-1 接收数据的校验 - is_valid()
5-2 数据的修改 - instance=修改对象 + Ser类实例.save()
5-3 局部校验钩子 - validate_field_name - 用于单个字段的校验定义
5-3 全局校验钩子 - validate - 用于多个字段的组合校验
一、Django内置的serializers模块 - 将对象序列化
1-1 单表操作(单表的get获取以及数据化)
# 用django自带的序列化组件序列化 from django.core import serializers import json class Books(APIView): def get(self,request): response = {'status': 100, 'data': None} books = models.Book.objects.all() # 先构造出所有书籍的字典的列表,即将获取的所有书本对象进行json格式序列化操作 ret=serializers.serialize('json',books) print(ret) # ret为json格式 # [{"model": "app01.book", "pk": 1, "fields": {"name": "name", "price": "123"}}, {"model": "app01.book", "pk": 2, "fields": {"name": "\u6c34", "price": "15"}}, {"model": "app01.book", "pk": 3, "fields": {"name": "\u6c34\u90fd\u662f", "price": "15"}}] # 将json数据存入返回结构内,注意前台取出的data需要进行反序列化操作 # 不建议将json格式放入字典内,建议将原始数据放入 response['data'] = json.loads(ret) # 注意不能将字典(对象)格式使用HTTP直接返回前台 return HttpResponse(response)
二、DRF框架 - Serializer 组件
2-1 单表操作
from rest_framework.views import APIView from rest_framework.serializers import Serializer from rest_framework import serializers # 写一个与modles内表类对应的Serializer类,用于获取需求序列化的字段 # 字段必须在modles对应表内进行定义 class BookSerializer(Serializer): name = serializers.CharField() # price=serializers.CharField() # date=serializers.CharField() class Books(APIView): def get(self, request): # 序列化多个对象(many=True) books = models.Book.objects.all() # instance=books要序列化的queryset对象,many=True,表示序列化多条 ser = BookSerializer(instance=books, many=True) print(ser.data) # [OrderedDict([('name', 'name')]), OrderedDict([('name', '水')]), OrderedDict([('name', '水都是')])] # instance:可以不写,按位置传 - instance位于位置传参的第一位 # ser=BookSerializer(books,many=True) # 序列化单个对象 many=False book = models.Book.objects.all().first() ser=BookSerializer(book,many=False) # ser.data 拿到的是序列化之后的字典,字典里可能套了列表,所以safe=False return JsonResponse(ser.data, safe=False)
2-1-1 缺少 safe=False 的错误信息 - 防止序列化的字典内套了列表
2-2 多表操作
2-2-1 models结构
from django.db import models # Create your models here. class Book(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) publish_date = models.DateField() publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE) authors = models.ManyToManyField(to='Author') def __str__(self): return self.name class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() author_detail = models.OneToOneField(to='AuthorDatail', to_field='nid', unique=True, on_delete=models.CASCADE) class AuthorDatail(models.Model): nid = models.AutoField(primary_key=True) telephone = models.BigIntegerField() birthday = models.DateField() addr = models.CharField(max_length=64) class Publish(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name def test(self): return self.email
2-2-2 View视图函数
from ap01 import models from rest_framework.views import APIView from django.http import JsonResponse from ap01.mySer import BookSerializer class Books(APIView): def get(self,request,*args,**kwargs): # 基于多个对象的序列化 many=True ret=models.Book.objects.all() book_ser=BookSerializer(ret,many=True) print(book_ser.data) return JsonResponse(book_ser.data,safe=False)
2-2-3 serializers 自定义类 - 等待view视图函数对象的传入,以及对象处理的逻辑
注意:
- 使用source参数可指定字段名对应的字段内容
- price = serializers.CharField() - 不使用source,则属性名字必须和字段一一对应
- xx = serializers.CharField(source='name') - 使用source,xx属性对应传入对象的name字段
- city = serializers.CharField(source='publish.city') - 使用source,city属性对应关系表publish表内的city字段
- test = serializers.CharField(source='publish.test') - 使用source,test属性对应关系表publish表内的test方法
- SerializerMethodField 必须结合自定义指定格式方法进行操作
- 可以在 get_字段名 方法内继续使用serializers序列化操作
from rest_framework import serializers class AuthorSerializer(serializers.Serializer): nid = serializers.CharField() name = serializers.CharField() age = serializers.CharField() class BookSerializer(serializers.Serializer): # source的使用 xx = serializers.CharField(source='name') price = serializers.CharField() city = serializers.CharField(source='publish.city') test = serializers.CharField(source='publish.test') publish_id = serializers.CharField() ''' SerializerMethodField 对应指定方法获取返回值 方法格式:get_字段名;必传参数:self,当前对象obj(book) publish=serializers.SerializerMethodField() def get_publish(self,obj): # obj 是当前book对象0 dic={'name':obj.publish.name,'email':obj.publish.email} return dic ''' authors = serializers.SerializerMethodField() # def get_authors(self,book): # #拿到这本书的所有作者 # aus=book.authors.all() # # 拼出一个列表,列表中套字典,每个字典是一个作者 # ll=[] # for a in aus: # ll.append({'name':a.name,'age':a.age}) # return ll def get_authors(self, book): # 拿到这本书的所有作者 aus = book.authors.all() # 可以继续用序列化类,来处理 auth_ser = AuthorSerializer(aus, many=True) return auth_ser.data
三、DRF框架 - ModelSerializer组件
总结:
- ModelSerializer组件必须配合Meta使用,对指定的字段进行序列化处理和返回
- Meta内注意事项:
from ap01.models import Book from rest_framework import serializers class AuthorSerializer(serializers.Serializer): nid = serializers.CharField() name = serializers.CharField() age = serializers.CharField() class BookSerializer(serializers.ModelSerializer): # 必须写一个Meta内部类 class Meta: # 序列化的对象,models内的对应表类 # 需导入from ap01.models import Book model = Book # 对表内所有字段进行序列化处理 fields = '__all__' # 指定只取这两个字段 # fields = ['nid','name'] # 去掉指定的字段,选入字段不进行序列化且不返回 # exclude=['publish','authors'] # fields,跟exclude不能连用 # 指定深度(官方建议小于10,我给你的建议小于3),和关联表的深度 - 不建议使用 # depth = 2 # 重写属性,覆盖Meta内初始化操作 publish = serializers.CharField(source='publish.name') authors = serializers.SerializerMethodField() def get_authors(self, book): # 拿到这本书的所有作者 aus = book.authors.all() # 可以继续用序列化类,来处理 auth_ser = AuthorSerializer(aus, many=True) return auth_ser.data
四、DRF - HyperlinkedIdentityField组件 - 用于链接的拼接
''' mySer.py HyperlinkedIdentityField 必传参数: - view_name:urls.py路由文件内反向解析名 - lookup_field:models内对应路由传入的参数 - lookup_url_kwarg:urls.py路由文件内对应有名参数名 - 注意:可以传入跨表字段,必须是联系表 例如:假设publish表类内存在外联关系表book - 'book_id' ''' class PublishSerializer(serializers.Serializer): name = serializers.CharField() city = serializers.CharField() publish_url = serializers.HyperlinkedIdentityField(view_name='urls_publish',lookup_field='nid',lookup_url_kwarg='id') ''' urls.py ''' url(r'^publish/(?P
\d+)', views.Publish.as_view(),name='urls_publish'), ''' views.py PublishSerializer 必传参数: - instance:序列化对象 - mangy:序列化对象的单复数 - context:获取链接中的域名,即 http://127.0.0.1:8000 ''' class Publish(APIView): def get(self, request, *args, **kwargs): ret = models.Publish.objects.all() publish_ser = PublishSerializer(ret, many=True,context={'request': request}) return JsonResponse(publish_ser.data, safe=False)
五、DRF - 反序列化
5-1 接收数据的校验 - is_valid()
注意:
- 校验通过的数据自动存储:ser.save()
- 校验未通过的数据形成错误报告:ser.errors
- 校验规则以models内定义的为基础,可以再其基础上在mySer文件内进行规则设定(方式同Form组件)
''' mySer.py 获取序列化数据、设置校验规则 ''' class PublishSerializer(serializers.ModelSerializer): class Meta: model = models.Publish fields = '__all__' # 自定义校验规则 # name = serializers.CharField(min_length=2, error_messages={'required': '必填字段'}) # city = serializers.CharField(required=False) ''' view.py视图 接收数据(JSON格式)进行校验 - 校验通过使用save将反序列化数据存入数据库 若存在校验错误 - 存储在errors内 ''' class Publish(APIView): def post(self, request, *args, **kwargs): response = {'status': 100, 'msg': '成功'} ser = PublishSerializer(data=request.data) if ser.is_valid(): ser.save() else: response['status'] = 101 response['msg'] = ser.errors return JsonResponse(response, safe=False)
5-2 数据的修改 - instance=修改对象 + Ser类实例.save()
''' urls.py ''' from django.conf.urls import url from django.contrib import admin from ap01 import views urlpatterns = [ # 由于publish两种路由,所以前者无参路由必须使用结束符 url(r'^publish/$', views.Publish.as_view()), url(r'^publish/(?P
\d+)', views.Publish.as_view(),name='urls_publish'), ] ''' mySer.py - 校验规则 ''' class PublishSerializer(serializers.ModelSerializer): class Meta: model = models.Publish fields = '__all__' name = serializers.CharField(min_length=2, error_messages={'required': '必填字段'}) email = serializers.CharField(required=False) ''' views.py - put数据提交修改数据库内容 ''' class Publish(APIView): def put(self, request, id, *args, **kwargs): response = {'status': 100, 'msg': '成功'} # 获取修改数据的单个对象 + 提交的数据 ret = models.Publish.objects.all().filter(pk=id).first() ser = PublishSerializer(data=request.data, instance=ret) if ser.is_valid(): ser.save() else: response['status'] = 101 response['msg'] = ser.errors return JsonResponse(response, safe=False) 5-3 局部校验钩子 - validate_field_name - 用于单个字段的校验定义
''' 局部校验钩子:validate_字段名 校验不通过 - 抛出指定ValidationError异常 (from rest_framework.exceptions import ValidationError) 校验通过 - 返回校验通过的对象值 ''' from rest_framework.exceptions import ValidationError class PublishSerializer(serializers.ModelSerializer): class Meta: model = models.Publish fields = '__all__' name = serializers.CharField(min_length=2, error_messages={'required': '必填字段'}) email = serializers.CharField(required=False) def validate_name(self, value): pub = models.Publish.objects.all().filter(name=value).first() if pub: raise ValidationError('同名对象已存在!') else: return value
5-3 全局校验钩子 - validate - 用于多个字段的组合校验
''' 全局校验钩子:validate 若校验不通过:抛出错误ValidationError 若校验通过:返回校验通过的对象 ''' from rest_framework.exceptions import ValidationError class PublishSerializer(serializers.ModelSerializer): class Meta: model = models.Publish fields = '__all__' name = serializers.CharField(min_length=2, error_messages={'required': '必填字段'}) email = serializers.CharField(required=False) def validate_name(self, value): pub = models.Publish.objects.all().filter(name=value).first() if pub: raise ValidationError('同名对象已存在!') else: return value def validate(self, attrs): # attrs 是所有校验通过数据的字典 name = attrs.get('name') city = attrs.get('city') if name == city: raise ValidationError('出版社名不可与城市名相同!') else: return attrs