DRF-序列化类Serializer的反序列化-局部和全局钩子-序列化类ModelSerializer的使用
作者:互联网
不使用drf编写5个接口
1.1路由
urlpatterns = [ path('books/', views.BookView.as_view()), path('books/<int:pk>', views.BookDetailView.as_view()), ]
1.2视图类
# 图书新增:psot 图书查询所有:get 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}) # 图书查询一个:get ,图书修改一个:put ,图书删除一个:delete 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':"修改成功"})
序列化类Serializer的反序列化
3.1使用drf的APIView写五个接口
from rest_framework.views import APIView # 图书新增:psot 图书查询所有:get 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): # 前端传入的,继承了APIView 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}) # 图书查询一个:get ,图书修改一个:put ,图书删除一个:delete 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':"修改成功"})
3.2使用APIView+序列化类(序列化:查单个,查所有)+Response来写五个接口
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也能映射成功
视图类
from rest_framework.views import APIView from rest_framework.response import Response from .serializer import BookSerializer # 图书新增:psot 图书查询所有:get 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): # 前端传入的,继承了APIView 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 Response({'msg':'新增成功','code':100}) # 图书查询一个:get ,图书修改一个:put ,图书删除一个:delete 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.all().filter(pk=pk).first() book.price=request.data.get('price') book.name=request.data.get('name') book.save() return Response({'code':100,'msg':"修改成功"})
3.3使用APIView+序列化类(序列化:查单个,查所有,反序列化:新增一个,修改一个)+Response来写五个接口
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): # 代码一点没少写,甚至多了,好处解耦了,view代码少了 # validated_data就是校验过后的数据 # 高级 book=Book.objects.create(**validated_data) # 菜鸡 # name=validated_data.get('name') # price=validated_data.get('price') # book = Book.objects.create(name=name,price=price) return book # 一定要return新增的对象 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 # 一定要return新增的对象
视图类
from rest_framework.views import APIView from rest_framework.response import Response from .serializer import BookSerializer # 图书新增:psot 图书查询所有:get 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): # 反序列化---》传得是data=前端传入的数据request.data ser=BookSerializer(data=request.data) # 数据校验 if ser.is_valid(): # forms组件就这么做的 # 保存-->会报错----》需要在序列化类中重写create方法 ser.save() return Response({'msg':'新增成功','code':100}) else: print(ser.errors) return Response({'msg': '数据没有校验通过', 'code': 101}) # 图书查询一个:get ,图书修改一个:put ,图书删除一个:delete 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=Book.objects.filter(pk=pk).first() # 使用data的数据,修改book这个对象 ser = BookSerializer(instance=book,data=request.data) if ser.is_valid(): # 会报错,需要重写序列化类的updata方法 ser.save() return Response({'code':100,'msg':"修改成功"}) else: return Response({'code': 101, 'msg': "修改失败"})
3.4总结重点
# 改了put方法和post方法 # 1 在视图类中使用 # 新增 ser=BookSerializer(data=request.data) if ser.is_valid(): ser.save() # 修改 ser=BookSerializer(instance=book,data=request.data) if ser.is_valid(): ser.save() # 2 在序列化类中,重写create和updata 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 # 一定要return新增的对象 #### 每个字段有自己的校验规则##### # 数据校验---》序列化类的字段,有字段属性 # 在字段上加属性---》就会按这个属性校验 name=serializers.CharField(max_length=8,min_length=3) price=serializers.CharField(min_length=1000) # 写成CharField也能映射成功 # 拿到数据校验失败的原因 ser.errors #### 校验是否是以sb开头---》参照forms组件的---》局部钩子,全局钩子
局部和全局钩子
# 无论新增还是修改,只要执行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=attrs.get('price') # 加判断,如果通过,就返回attrs # 如果不通过就抛异常 if name == price: raise ValidationError('名字和价格不能一样') else: return attrs
序列化类ModelSerializer的使用
# Serializer基类,序列化类都要继承它,写字段,重写create和updata方法 # 有没有一种简单方案,不写字段了(因为字段跟表有对应关系),不写update和create了 # 原来必须要重写update和create了的原因是---》新增不知道要增加到哪个表中去 # ModelSerializer就可以完成---》跟表有对应关系---》字段不用写了,存到哪也知道,不写update和create了 # 重点: 1 class Meta: 中model和fields意思 2 给字段类加属性 extra_kwargs 3 局部全局钩跟之前没有任何区别 4 create和update不需要写了 5 可以重写某个字段,但注意缩进 class BookSerializer(serializers.ModelSerializer): # 要序列化的字段,没有写,但是写了model=Book,它自动把Book表中的字段映射出来,相当于 # name = serializers.CharField(max_length=32) # price = serializers.IntegerField() # 缩进关系搞懂 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) # 之前教的局部钩子和全局钩子完全一样,一毛一样 # 不需要重写create和update方法了,因为ModelSerializer已经写了
标签:ModelSerializer,name,get,price,request,book,序列化,data,Serializer 来源: https://www.cnblogs.com/wql0817/p/16415050.html