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嵌套

https://www.cnblogs.com/wuxiaoshi/p/11831466.html

posted @ 2023-02-26 16:14  MISF  阅读(13)  评论(0编辑  收藏  举报
     JS过度和变形效果演示   
  
    html5.png