rest_framework序列化之Serializer
步骤:
1.自定义一个类,继承Serializer类;
2.在类中写要序列化的字段;
3.使用:在views.py文件中,book_ser=BookSerializer(book_list,many=True),book_ser.data就是序列化后的数据。当序列化的数据有多条(为QuerySet对象)时设置many=True,当序列化的数据只有一条(为obj对象)时设置many=False。
models部分:
from django.db import models # Create your models here. class Book(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.ForeignKey(to='Publish', null=True, on_delete=models.SET_NULL, db_constraint=False)
author = models.ManyToManyField(to='Author', db_constraint=False) class Publish(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
address = models.CharField(max_length=16) class Author(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
author_detail = models.OneToOneField(to='AuthorDetail', null=True, on_delete=models.SET_NULL, db_constraint=False) class AuthorDetail(models.Model):
id = models.AutoField(primary_key=True)
age = models.IntegerField()
sex = models.SmallIntegerField(default=0)
info = models.CharField(max_length=128)
views部分:
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)
price=serializers.IntegerField()
pub_date=serializers.DateField()
publish=serializers.CharField(source="publish.name")
#authors=serializers.CharField(source="authors.all")
authors=serializers.SerializerMethodField()
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):
# ret=obj.authors.all()
# ss=AuthorSerializer(ret,many=True)
# return ss.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(book_list,many=True) #many=True代表有多条数据,如果只有一条数据,many=False
return Response(bs.data)
# 序列化方式4:
# ret=models.Book.objects.all().values('nid','title')
# dd=list(ret)
# return HttpResponse(json.dumps(dd))
注:
1.source指定的如果是字段,则会显示字段,如果是方法,则会执行方法,不用加括号(books=serializers.CharField(source='books.all'));
2.SerializerMethodField,必须配合方法使用 get_字段名(self,obj),obj是当前要序列化的对象;
3.SerializerMethodField对应的方法中还可以继续使用其他的序列化类。
rest_framework序列化之ModelSerializer
步骤:
1.自定义一个类继承ModelSerializer;
2.在类内部写:
class Meta:
model=models.Book
fields='__all__'
# exclude=['name','price']
depth=1
class BookSerializers(serializers.ModelSerializer):
class Meta:
model = models.Book
# fields = "__all__"
fields=['nid','title','authors','publish']
# exclude=('nid',) #不能跟fields同时用
# depth = 1 #深度控制,写 几 往里拿几层,层数越多,响应越慢,官方建议0--10之间,个人建议最多3层
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(ret,many=True)
return ss.data
请求数据校验和保存:
class BooksView(APIView):
def post(self, request):
response = {'status': 200, 'msg': '修改成功'}
try:
obj_ser = self.BookSerializer(data=request.data)
if obj_ser.is_valid(): # 校验
obj_ser.save() # 生成记录
response['data'] = obj_ser.data
else:
response['msg'] = obj_ser.errors
except Exception as e:
response['msg'] = str(e)
return Response(response)
校验字段局部和全局钩子函数:
class BookSerialzers(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = '__all__'
depth = 1 #局部钩子函数,validate_字段名,value字段的值
def validate_name(self, value):
if re.match('^[0-9]+', value):
raise ValidationError('书名不能以数字开头')
return value #全局钩子函数,对全局字段进行校验
def validate(self,objdict):
name=objdict.get('name')
price=objdict.get('price')
if name != price:
raise ValidationError('错了')
else:
return objdict