drf序列化
一.models
包含一对一、一对多、多对多
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
name = models.CharField(max_length=20)
tel = models.CharField(max_length=20)
class Books(models.Model):
name = models.CharField(max_length=20)
type = models.IntegerField(choices=((1,"玄幻"),(2,"历史")))
price = models.IntegerField(default=0)
addr = models.OneToOneField(to="BookAddr",default=3,on_delete=models.CASCADE)
date1 = models.DateTimeField(auto_now=True)
class Authors(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField()
address = models.CharField(max_length=20)
books = models.ManyToManyField(Books)
class BookDetail(models.Model):
detail = models.CharField(max_length=20,verbose_name="详细信息")
# 一篇文章对应多个详细内容
book = models.ForeignKey(to="Books",on_delete=models.CASCADE,related_name="details")
class BookAddr(models.Model):
addr = models.CharField(max_length=20,verbose_name="时区")
# def __str__(self):
# return self.addr
二.序列化
注意序列化的作用:是将model对象转为json对象,供Response返回
models同级新建serializers.py
1.序列化
当前代码只是序列化作用(用来传给前端的)
- fields是用来传给前端的字段,可写成
__all__
,正常来说不用下面的detail、date1等字段,这些字段是为了重写一些方法,用来方便传输 - read_only参数在序列化时要传到前端,但前端反序列化时不用再传给后端
- 定义了SerializerMethodField方法后,要和get_字段连用
- DateTimeField字段手动添加无法显示,代码添加时会自动更新
- extra_kwargs定义字段额外的一些参数
from user import models
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Books
fields = ["name","type","price","date1","detail","addr"] # __all__
detail = serializers.SerializerMethodField(read_only=True)
date1 = serializers.DateTimeField(read_only=True,required=False)
addr = serializers.SerializerMethodField(read_only=True)
#extra_kwargs = {
# 'detail': {'write_only': True},
# 'addr': {'read_only': True},
#}
def get_addr(self,obj):
return obj.addr.addr
def get_detail(self,obj):
res_lst = []
for ob in obj.details.all():
res_lst.append({"id":ob.id,"detail":ob.detail})
return res_lst
2.反序列化
反序列化会加上validate(全局校验)、validate_字段名等,后端传来数据会进行验证
from user import models
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Books
fields = ["name","type","price","date1","detail","addr"]
detail = serializers.SerializerMethodField(read_only=True)
date1 = serializers.DateTimeField(read_only=True,required=False)
addr = serializers.SerializerMethodField(read_only=True)
def get_addr(self,obj):
return obj.addr.addr
def get_detail(self,obj):
res_lst = []
for ob in obj.details.all():
res_lst.append({"id":ob.id,"detail":ob.detail})
return res_lst
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = models.Authors
fields = "__all__"
class AddrSerializer(serializers.ModelSerializer):
class Meta:
model = models.BookAddr
fields = ["addr"]
def validate(self, attrs):
if attrs.get("addr") == "上号":
return attrs
else:
raise serializers.ValidationError("错误信息")
三.查询
查询单条数据: http://127.0.0.1:8001/books/?pk=1
查询所有数据: http://127.0.0.1:8001/books/
from django.shortcuts import render
# Create your views here.
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView,ListAPIView
from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from django.contrib.auth import authenticate,login,logout
from .serializers import BookSerializer,AddrSerializer
from user import models
class BookView(APIView):
def get(self,request,*args,**kwargs):
print(kwargs,args,request.query_params)
# print(pk,"pk")
# pk = 1
pk = request.query_params.get("pk")
if not pk:
queryset_obj = models.Books.objects.all()
res = BookSerializer(instance=queryset_obj,many=True)
return Response(res.data)
else:
queryset_obj = models.Books.objects.filter(id=pk).first()
res = BookSerializer(instance=queryset_obj,many=False)
return Response(res.data)
urls.py
url(r'^books/$',views.BookView.as_view()),
四.增加
1.单表添加
class BookView(APIView):
def post(self,request,*args,**kwargs):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response("添加成功!")
return Response(ser.errors)
urls.py
url(r'^books/$',views.BookView.as_view()),
2.连表添加
1.普通写法
连表添加需要上传的json数据和俩个反序列化中规定的字段一样
class BookView(APIView):
def post(self,request,*args,**kwargs):
ser = BookSerializer(data=request.data)
addr = AddrSerializer(data=request.data)
if ser.is_valid() and addr.is_valid():
#不同的序列化器得到的是属于自己的validated_data
print(ser.validated_data)
#OrderedDict([('name', '水浒1'), ('type', 2), ('price', 23)])
print(addr.validated_data)
#sdf OrderedDict([('addr', '上号')])
addr_obj = addr.save(addr=request.data.get("addr"))
ser.save(addr=addr_obj)
return Response("添加成功!")
return Response(ser.errors)
2.序列化器中重写create方法
create方法没上面的好用,因为上面是直接addr.save(),将前端传来的addr序列化对象的值全部存入了,create需要自己拆分validated_data,addr.save()是会调用create方法的。
3.多对多
此文章运用了serializer嵌套