Django内置的serializers(把对象序列化成json字符串
from django.core import serializers def test(request): book_list = Book.objects.all() ret = serializers.serialize("json", book_list) return HttpResponse(ret)
二 rest-framework序列化之Serializer
models部分
from django.db import models # Create your models here. class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") authors=models.ManyToManyField("Author") def __str__(self): return self.title class Publish(models.Model): name=models.CharField(max_length=32) email=models.EmailField() def __str__(self): return self.name class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() def __str__(self): return self.name
view部分
from rest_framework.views import APIView from rest_framework.response import Response from .models import * from django.shortcuts import HttpResponse from django.core import serializers from rest_framework import serializers class BookSerializers(serializers.Serializer): title=serializers.CharField(max_length=32) #title3=serializers.CharField(source='title') # 指定source='title' ,表示序列化模型表中的title字段,重名命为title3(title和source='title'指定的name不能重名) price=serializers.IntegerField() pub_date=serializers.DateField() publish=serializers.CharField(source="publish.name") # source不但可以指定一个字段,还可以指定一个方法,如果是方法,会执行方法,不用加括号 #authors=serializers.CharField(source="authors.all") # 序列化出版社的详情,指定SerializerMethodField之后,可以对应一个方法,返回什么内容,publish_detail就是什么内容 authors=serializers.SerializerMethodField(read_only=True) # write_only 序列化的时候,该字段不显示 # #read_only 反序列化的时候,该字段不传 # #对应的方法固定写法get_字段名 def get_authors(self,obj): temp=[] for author in obj.authors.all(): temp.append(author.name) return temp #此处可以继续用author的Serializers, # def get_authors(self,obj): #方法一: # return [ {'name':author.name,'age':author.age} for author in obj.authors.all()] #方法二: # ret=obj.authors.all() # ss=AuthorSerializer(ret,many=True) # return ss.data
#需要重写Crete方法
def create(self,validated_data):
res = models.Book.objects.create(**validated_data)
return authorser.data
class BookViewSet(APIView): def get(self,request,*args,**kwargs): book_list=Book.objects.all() # 序列化方式1: # from django.forms.models import model_to_dict # import json # data=[] # for obj in book_list: # data.append(model_to_dict(obj)) # print(data) # return HttpResponse("ok") # 序列化方式2: # data=serializers.serialize("json",book_list) # return HttpResponse(data) # 序列化方式3: bs=BookSerializers(initial=book_list,many=True) #many=True代表有多条数据,如果只有一条数据(可以不写),many=False.(可以不写).instance是要序列化的对象 return Response(bs.data) # 序列化方式4: # ret=models.Book.objects.all().values('nid','title') # dd=list(ret) # return HttpResponse(json.dumps(dd)) # 使用继承了Serializers序列化类的对象,反序列化 def post(self,request): # #实例化产生一个序列化类的对象,data是要反序列化的字典 # # print(request.data) bookser=BookSerializers(data=request.data) if bookser.is_valid(): # #清洗通过的数据 ret=bookser.create(bookser.validated_data) # return Response()
如在模型中定义一个方法,直接可以在在source指定执行:
class UserInfo(models.Model): user_type_choices = ( (1,'普通用户'), (2,'VIP'), (3,'SVIP'), ) user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32,unique=True) password = models.CharField(max_length=64) #视图 ret=models.UserInfo.objects.filter(pk=1).first() aa=ret.get_user_type_display() #serializer xx=serializers.CharField(source='get_user_type_display')
rest-framework序列化之ModelSerializer
from rest_framework import serializers from rest_framework.response import Response from app01 import models class AuthorSerializer(serializers.Serializer): name=serializers.CharField() age=serializers.CharField() class BookSerializers(serializers.ModelSerializer): class Meta: model = models.Book #展示全部 # fields = "__all__" #可以允许展示的 fields=['nid','title','authors','publish'] #不允许展示的 # exclude=('nid',) #不能跟fields同时用 # depth = 1 #深度控制,写 几 往里拿几层,层数越多,响应越慢,官方建议0--10之间,个人建议最多3层 # xx=serializers.CharField(source='get_xx_display') publish=serializers.SerializerMethodField() def get_publish(self,obj): return obj.publish.name #这种方法到了后期可以在家字段 authors=serializers.SerializerMethodField() def get_authors(self,obj): ret=obj.authors.all() ss=AuthorSerializer(initial=ret,many=True) return ss.data # 使用继承了ModelSerializers序列化类的对象,反序列化
def post(self, request): # 实例化产生一个序列化类的对象,data是要反序列化的字典 bookser = BookSerializers(data=request.data) # bookser.data if bookser.is_valid(raise_exception=True): # 清洗通过的数据 bookser.save() else: print(bookser.errors['name'][0]) return Response()
五 序列化组件之请求数据校验和保存功能
class BookSerializer1(serializers.Serializer): title=serializers.CharField(error_messages={'required': '标题不能为空'}) #这种方式要保存,必须重写create方法
通过源码查看留的校验字段的钩子函数:
#反序列化的校验(局部校验,全局校验) #使用钩子一般都是字段写出来,而不是用__all__方法 def validate_name(self,value): print(value) raise exceptions.ValidationError('不能以sb开头') # if value.startswith('sb'): # raise ValidationError('不能以sb开头') # return value def validate(self,attrs): print(attrs) # if attrs.get('price')!=attrs.get('xx'): # raise exceptions.ValidationError('name和price相等,不正常') return attrs
view视图
def post(self,request): #实例化产生一个序列化类的对象,data是要反序列化的字典 bookser=BookSerializer(data=request.data) # bookser.data #raise_seception=True错误会显示到前端 if bookser.is_valid(raise_exception=True): #清洗通过的数据 bookser.save() else: print(bookser.errors['name'][0]) return Response()
序列化组件源码分析
序列化组件,先调用__new__方法,如果many=True,生成ListSerializer对象,如果为False,生成Serializer对象 序列化对象.data方法--调用父类data方法---调用对象自己的to_representation(自定义的序列化类无此方法,去父类找) Aerializer类里有to_representation方法,for循环执行attribute = field.get_attribute(instance) 再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source,然后执行get_attribute方法,source_attrs 当参数传过去,判断是方法就加括号执行,是属性就把值取出来
图书的增删查改resful接口:
视图层:
class BookSerializers(serializers.ModelSerializer): class Meta: model=models.Book fields='__all__' class BookView(APIView): def get(self, request): book_list = models.Book.objects.all() bs = BookSerializers(book_list, many=True) # 序列化数据 return Response(bs.data) def post(self, request): # 添加一条数据 print(request.data) bs=BookSerializers(data=request.data) if bs.is_valid(): bs.save() # 生成记录 return Response(bs.data) else: return Response(bs.errors) class BookDetailView(APIView): def get(self,request,pk): book_obj=models.Book.objects.filter(pk=pk).first() bs=BookSerializers(book_obj,many=False) return Response(bs.data) def put(self,request,pk): book_obj = models.Book.objects.filter(pk=pk).first() bs=BookSerializers(data=request.data,instance=book_obj) if bs.is_valid(): bs.save() # update return Response(bs.data) else: return Response(bs.errors) def delete(self,request,pk): models.Book.objects.filter(pk=pk).delete() return Response("")
路由:
url(r'^books/$', views.BookView.as_view()), url(r'^books/(?P<pk>\d+)$', views.BookDetailView.as_view()),