drf 03——Serializer、ModelSerializer

1 不使用drf编写5个接口

1.1路由

urlpatterns = [
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>', views.BookDetailView.as_view()),
]

1.2视图类

class BookView(View):
    def get(self, request):
        books = []
        book_list = Book.objects.all()
        # book_list = [book1, book2]
        # 组装成 [{name: 静夜思, pirce: 18}, {name: 静夜思, pirce: 18}]
        for book in book_list:
            books.append({'id':book.id,'name': book.name, 'price': book.price})
        return JsonResponse(books, safe=False,json_dumps_params={'ensure_ascii':False})

    def post(self,request):
        # 前端传入的
        name = request.POST.get('name')
        price = request.POST.get('price')
        # 存到表中
        book = Book.objects.create(name=name,price=price)
        # return JsonResponse({'id':book.id,'name':book.name,'price':book.price})
        return JsonResponse({'msg':'新增成功','code':100})

class BookDetailView(View):
    def get(self,request,pk):
        book = Book.objects.all().filter(pk=pk).first()
        return JsonResponse({'id':book.id,'name':book.name,'pirce':book.price})
    
    def delete(self,request,pk):
        Book.objects.all().filter(pk=pk).delete()
        return JsonResponse({'code':100,'msg':"删除成功"})

    def put(self,request,pk):
        # 前端传入的,put请求从django 的POST取不出来
        import json
        try:
            data = json.loads(request.body)
        except Exception as e:
            data = request.POST
        request.data = data
        book = Book.objects.all().filter(pk=pk).first()
        book.price = request.data.get('price')
        book.name = request.data.get('name')
        book.save()
        return JsonResponse({'code':100,'msg':"修改成功"})

2 序列化类Serializer的反序列化

2.1 使用drf的APIView写5个接口

from rest_framework.views import APIView

class BookView(APIView):
    def get(self, request):
        books = []
	book_list = Book.objects.all()
	for book in book_list:
            books.append({'id':book.id,'name': book.name, 'price': book.price})
	return JsonResponse(books, safe=False, json_dumps_params={'ensure_ascii': False})

    def post(self, request):        
	name = request.data.get('name')
	price = request.data.get('price')
	book = Book.objects.create(name=name, price=price)
        # return JsonResponse({'id': book.id, 'name': book.name, 'price': book.price})
        return JsonResponse({'msg': '新增成功', 'code': 100})
    
class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.all().filter(pk=pk).first()
        return JsonResponse({'id': book.id, 'name': book.name, 'pirce': book.price})
    
    def delete(self, request, pk):
        Book.objects.all().filter(pk=pk).delete()
        return JsonResponse({'code': 100, 'msg': "删除成功"})

    def put(self, request, pk):
        book = Book.objects.all().filter(pk=pk).first()
        book.price = request.data.get('price')
        book.name = request.data.get('name')
        book.save()
        return JsonResponse({'code': 100, 'msg': "修改成功"})    

2.2 使用APIView+序列化类+Response写5个接口

# 序列化	
	查单个	查所有	两个get
# 反序列化
	新增单个	post
	修改单个	put

序列化类

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.Serializer):
    # read_only=True  意思是只读,只用来做序列化,不用来做反序列化
    # 如果不写read_only=True,这个字段必传,如果不传,数据校验不过
    # 如果写了read_only=True,这个字段不传
    id = serializers.IntegerField(read_only=True)  # model中Auto,本质就是数字,IntegerField
    name = serializers.CharField(max_length=8,min_length=3,
                                 error_messages={'max_length':'太长了'})
    # price = serializers.IntegerField()
    price = serializers.CharField(max_length=1000)  # 写成CharField也能映射成功
    
    def create(self, validated_data):
        book = Book.objects.create(**validated_data)
        return book

    def update(self, instance, validated_data):
        # instance 是要修改的对象
        # validated_data是校验过后数据
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.save()   
        return instance    

视图类

from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer

class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        ser = BookSerializer(instance=book_list, many=True)
        return Response(ser.data)
    
    def post(self,request):
        ser = BookSerializer(data=request.data)
        # 数据校验
        if ser.is_valid():  
            # 直接保存报错 需要在序列化类中重写create方法
            ser.save()
            return Response({'msg':'新增成功','code':100})
        else:
            print(ser.errors)
            return Response({'msg': '数据没有校验通过', 'code': 101})

class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.all().filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response(ser.data)
    
    def delete(self, request, pk):
        Book.objects.all().filter(pk=pk).delete()
        return Response({'code':100,'msg':"删除成功"})

    def put(self, request, pk):     
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book, data=request.data)
        if ser.is_valid():
            # 直接保存报错 需要在序列化类中重写update方法
            ser.save()
            return Response({'code':100,'msg':"修改成功"})
        else:
            return Response({'code': 101, 'msg': "修改失败"})

重点

1 在视图类中使用
  # 新增	只要传数据(data)
   ser = BookSerializer(data=request.data)
   if ser.is_valid(): 
       ser.save()
    
  # 修改	要给对象(instance)传数据(data)	
   ser = BookSerializer(instance=book, data=request.data)
   if ser.is_valid(): 
       ser.save()       	      

校验完数据进行保存(save)的前提 还要重写create和update方法

2 在序列化类中 重写create和update方法
    def create(self, validated_data):
        book = Book.objects.create(**validated_data)
        return book 

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.save()   
        return instance  

3 局部钩子和全局钩子

新增及修改执行ser.is_valid()就会出发校验
# 校验顺序
	字段自身----->局部钩子----->全局钩子
    # 局部钩子,校验书名不能以sb开头   这里校验的字段形参 forms组件没有,validate有
    def validate_name(self, name):
        # name就是  要校验的字段对应的前端传入的值
        if name.startswith('sb'):
            # 校验失败,抛异常
            raise ValidationError('不能以sb开头')
        else:
            return name

    # 全局钩子
    def validate(self, attrs):
        # attrs为经过字段自身校验完后,局部钩子走完过的数据
        name = attrs.get('name')
        price = str(attrs.get('price'))
        # 加判断,如果通过,就返回attrs
        # 如果不通过就抛异常
        if name == price:
            raise ValidationError('名字和价格不能一样')
        else:
            return attrs

4 序列化类ModelSerializer

使用ModelSerializer的好处
	'Serializer' 需要重写create和update方法 是因为不知道新增和修改到那个表去	字段和表没有对应关系
	'ModelSerializer' 字段和表有对应关系 无需重写create和update方法    
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book    # 跟Book做对应
        # fields = '__all__'   # 序列化和反序列化Book中的所有字段
        fields = ['name', 'price']  # 只序列化和反序列化某几个字段
        # 重点: 如果不重写字段,但是我想给字段类加属性---》使用下面的方式
        # 如果不这样写,name会默认使用model的规则max_length=32
        # 如果这样写了,最大长度是8 ,最小长度是3
        extra_kwargs = {
            'name': {'max_length': 8, 'min_length': 3},
            'price': {'max_value': 88}
        }

    # 表示重写name这个字段,会走它的规则
    # name=serializers.CharField(max_length=8, min_length=3)
posted @   扶我上码  阅读(33)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示