rest_framework:序列化器类/视图
一.序列化器类
序列化就是把数据转换为json 在服务端发送到客户端 反序列化是客户端法的数据发送到服务端 服务端通过反序列化把数据转换为json from rest_framework import serializers serializers 是dfr提供给开发者调用的序列化模块 里面声明了所有可用序列化器的基类 serializer 序列化基类 drf中所有的序列化器类都必须继承serializer ModelSerializer 模型序列化器类 是序列化的子类 在工作中 除了serializer基类以外 最常用的序列化类基类
1).serializer
1.1转换的字段说明(序列化)
先在应用下创建序列化器文件 然后在文件中: class Serializer1(serializers.Serializer): # 1.转换的字段声明(把数据放到序列化器中就会转换为对应的类型) # 格式: 字段 = serializers.字段类型(选项=选项值) id = serializers.IntegerField() title = serializers.CharField()
urlpatterns = [ path('BookView/', views.BookView.as_view()), ]
1 from seriali.serializers import Serializer1 2 from django.views import View 3 from django.http.response import JsonResponse 4 from app01.models import Book 5 6 7 class BookView(View): 8 def get(self,request): 9 """序列化器-序列化阶段的调用""" 10 # 1.获取数据集 并把数据放到序列化器中 11 book_list = Book.objects.filter() 12 # print(book_list.title) 13 #2. 实例化序列化器 得到序列化方法 14 # 注意!!!: 传递到序列化器的模型对象如果是多个,务必使用many = True 如果是单独的比如 Book.objects.filter() 可以不加many=True 15 serializer = Serializer1(instance=book_list,many=True) 16 #3. 调用序列化器对象的data方法 这个方法会获取转换后的数据 17 data = serializer.data 18 return JsonResponse(data=data,status=201,safe=False)
1.2转换的字段说明(反序列化)
class Serializer(serializers.Serializer): # 1.转换的字段声明 # 比如id字段需要转换为json就可以写上 # 格式: 字段 = serializers.字段类型(选项=选项值) id = serializers.IntegerField(read_only=True,max_value=100,min_value=0,error_messages={"max_value":"最大值为100"}) # read_only=True 在客户端提交数据[反序列化阶段不会要求id字段] max_value=100表示值最大为一百 min_value=0表示值最小为0 title = serializers.CharField(required=True) # required=True 反序列化阶段必须 state = serializers.BooleanField(default=True) # default=True 反序列化阶段 客户端没有填写 默认为True pub_date = serializers.CharField(allow_blank=True,allow_null=True) # 允许客户端不填写内容(none) 或者值为""
urls.py
def get(self,request): # 反序列化数据--采用字段选项来验证数据 # 1.接受客户端提交的数据 args = json.loads(request.body.decode()) print(args) # 1.1. 实例化序列化器 获取序列化对象 serializer = Serializer(data=args) # 1.2 调用序列化器进行数据验证 # raise_exception=True表示如果有异常直接抛出 代码不会往下执行 ret = serializer.is_valid(raise_exception=True) #ret返回True表示成功 如果返回False表示失败 # 1.3 获取验证后的结果 if ret: print(serializer.validated_data) #serializer.validated_data 获取反序列化后的结果 else: print(serializer.errors) # serializer.errors 获取异常数据结果 # 2. 操作数据库 # pass # 3. 返回结果 return JsonResponse(data={}, status=201, safe=False)
1.3验证代码的对象方法
如果需要对一些字段和数据进行复杂的校验一共有两种方式
#格式是validate_字段名称 def validate_title(self,data): # 第一种 单独校验一个字段 格式 def validate_字段(self,data): print("正在校验title",data) if data in ["python","吴鸿昌"]: raise serializers.ValidationError(detail="包含敏感字符",code="name") return data
def validate(self,attrs): print(attrs["title"],"这是") return attrs # attrs表示所有字段 必须要这样写
1.4模型操作的方法
如果在实例化序列化器时,传入instance表示更新数据 否则表示添加数据
def create(self,validate_data): """ 添加数据 函数名必须叫create 参数validate_data也是固定的 :param validate_data: 表示验证以后的结果 :return: """ data = Book.objects.create(**validate_data) print("过来了数据") return data
def get3(self,request): # 反序列化数据--采用字段选项来验证数据 # 1.接受客户端提交的数据 args = json.loads(request.body.decode()) print(args,"看看数据") # 1.1. 实例化序列化器 获取序列化对象 serializer = Serializer(data=args) # 1.2 调用序列化器进行数据验证 # raise_exception=True表示如果有异常直接抛出 代码不会往下执行 serializer.is_valid(raise_exception=True) #ret返回True表示成功 如果返回False表示失败 serializer.save() # 写入数据 # 3. 返回结果 return JsonResponse(data={}, status=201, safe=False)
def update(self,instance,validate_data): """ 更新数据 方法名固定 :param instance:实例化序列化器对象时,必须传入的模型对象 :param validate_data: 验证成功以后的数据 :return: """ instance.title = validate_data["title"] instance.save() return validate_data
def get(self,request): # 更新数据 要先获取更新哪一条数据 也就是pk值 # urls.py: path("seriali/(?P<pk>\d+)/",views.BookView.as_view()) # 1.获取pk的值 pk=1 # 比如 book = Book.objects.get(pk=pk) # 2.获取要修改的值 args = json.loads(request.body.decode()) # 3.修改操作中的实例化序列化器对象 serializer = Serializer(instance=book,data=args) # 4.验证数据 serializer.is_valid(raise_exception=True) # 存数据 serializer.save() return JsonResponse(serializer.data, status=201, safe=False)
2).modelserializers
相对于父类(serializers),modelserializer自动实现了以下三个步骤:
- 可以根据指定的model自动检测并自动序列化的字段,不需要提前定义
- 自动为序列化生成校验器
- 自动实现了create()和update()
serializer的属性和方法:
1.save() 在调用serializer.save()时,会创建或者更新一个Model实例(调用create()或update()创建),具体根据序列化类的实现而定,如: 2.create()、update() Serializer中的create()和update()方法用于创建生成一个Model实例,在使用Serializer时,如果要保存反序列化后的实例到数据库,则必须要实现这两方法之一,生成的实例则作为save()返回值返回。方法属性validated_data表示校验的传入数据,可以在自己定义的序列化类中重写这两个方法。 3. is_valid() 当反序列化时,在调用Serializer.save()之前必须要使用is_valid()方法进行校验,如果校验成功返回True,失败则返回False,同时会将错误信息保存到serializer.errors属性中。 4.data serializer.data中保存了序列化后的数据。 5.errors 当serializer.is_valid()进行校验后,如果校验失败,则将错误信息保存到serializer.errors属性中。
serializer的Field:
1.CharField 对应models.CharField,同时如果指定长度,还会负责校验文本长度。 max_length:最大长度; min_length:最小长度; allow_blank=True:表示允许将空串做为有效值,默认False; 2.EmailField 对应models.EmailField,验证是否是有效email地址。 3.IntegerField 对应models.IntegerField,代表整数类型 4.FloatField 对应models.FloatField,代表浮点数类型 5.DateTimeField 对应models.DateTimeField,代表时间和日期类型。 format='YYYY-MM-DD hh:mm':指定datetime输出格式,默认为DATETIME_FORMAT值。 需要注意,如果在 ModelSerializer 和HyperlinkedModelSerializer中如果models.DateTimeField带有auto_now=True或者auto_add_now=True,则对应的serializers.DateTimeField中将默认使用属性read_only=True,如果不想使用此行为,需要显示对该字段进行声明: class CommentSerializer(serializers.ModelSerializer): created = serializers.DateTimeField() class Meta: model = Comment 6.FileField 对应models.FileField,代表一个文件,负责文件校验。 max_length:文件名最大长度; allow_empty_file:是否允许为空文件; 7.ImageField 对应models.ImageField,代表一个图片,负责校验图片格式是否正确。 max_length:图片名最大长度; allow_empty_file:是否允许为空文件; 如果要进行图片处理,推荐安装Pillow: pip install Pillow 8.HiddenField 这是serializers中特有的Field,它不根据用户提交获取值,而是从默认值或可调用的值中获取其值。一种常见的使用场景就是在Model中存在user_id作为外键,在用户提交时,不允许提交user_id,但user_id在定义Model时又是必须字段,这种情况下就可以使用HiddenField提供一个默认值: class LeavingMessageSerializer(serializers.Serializer): user = serializers.HiddenField( default=serializers.CurrentUserDefault() )
serializer的公共参数:
所谓公共参数,是指对于所有的serializers.<FieldName>都可以接受的参数。以下是常见的一些公共参数。 1.read_only read_only=True表示该字段为只读字段,即对应字段只用于序列化时(输出),而在反序列化时(创建对象)不使用该字段。默认值为False。 2.write_only write_only=True表示该字段为只写字段,和read_only相反,即对应字段只用于更新或创建新的Model时,而在序列化时不使用,即不会输出给用户。默认值为False。 3.required required=False表示对应字段在反序列化时是非必需的。在正常情况下,如果反序列化时缺少字段,则会抛出异常。默认值为True。 4.default 给字段指定一个默认值。需要注意,如果字段设置了default,则隐式地表示该字段已包含required=False,如果同时指定default和required,则会抛出异常。 5.allow_null allow_null=True表示在序列化时允许None作为有效值。需要注意,如果没有显式使用default参数,则当指定allow_null=True时,在序列化过程中将会默认default=None,但并不会在反序列化时也默认。 6.validators 一个应用于传入字段的验证函数列表,如果验证失败,会引发验证错误,否则直接是返回,用于验证字段,如: username = serializers.CharField(max_length=16, required=True, label='用户名', validators=[validators.UniqueValidator(queryset=User.objects.all(),message='用户已经存在')]) 7.error_message 验证时错误码和错误信息的一个dict,可以指定一些验证字段时的错误信息,如: mobile= serializers.CharField(max_length=4, required=True, write_only=True, min_length=4, label='电话', error_messages={ 'blank': '请输入验证码', 'required': '该字段必填项', 'max_length': '验证码格式错误', 'min_length': '验证码格式错误', }) 7.style 一个键值对,用于控制字段如何渲染,最常用于对密码进行密文输入,如: password = serializers.CharField(max_length=16, min_length=6, required=True, label='密码', error_messages={ 'blank': '请输入密码', 'required': '该字段必填', 'max_length': '密码长度不超过16', 'min_length': '密码长度不小于6', }, style={'input_type': 'password'}, write_only=True) 9.label 一个简短的文本字串,用来描述该字段。 10.help_text 一个文本字串,可用作HTML表单字段或其他描述性元素中字段的描述。 11.allow_blank allow_blank=True 可以为空 设置False则不能为空 12.source source='user.email'(user表的email字段的值给这值) 设置字段值 类似default 通常这个值有外键关联属性可以用source设置 13.validators 验证该字段跟 单独的validate很像 UniqueValidator 单独唯一 validators=[UniqueValidator(queryset=UserProfile.objects.all()) UniqueTogetherValidator: 多字段联合唯一,这个时候就不能单独作用于某个字段,我们在Meta中设置。 validators = [UniqueTogetherValidator(queryset=UserFav.objects.all(),fields=('user', 'course'),message='已经收藏')] 14.error_messages 错误消息提示 error_messages={ "min_value": "商品数量不能小于一", "required": "请选择购买数量" }) 7.ModelSerializers ModelSerializers继承于Serializer,相比其父类,ModelSerializer自动实现了以下三个步骤: 1.根据指定的Model自动检测并生成序列化的字段,不需要提前定义; 2.自动为序列化生成校验器; 3.自动实现了create()方法和update()方法。 使用ModelSerializer方式如下: class StudentSerializer(serializers.ModelSerializer): class Meta: # 指定一个Model,自动检测序列化的字段 model = StudentSerializer fields = ('id', 'name', 'age', 'birthday') 相比于Serializer,可以说是简单了不少,当然,有时根据项目要求,可能也会在ModelSerializer中显示声明字段,这些在后面总结。 model 该属性指定一个Model类,ModelSerializer会根据提供的Model类自动检测出需要序列化的字段。默认情况下,所有Model类中的字段将会映射到ModelSerializer类中相应的字段。
二.视图
1).两个视图基类
1.APIView
APIview是drf提供的所有视图的基类,继承的是Django的view APIview和view不同处: 1.传到视图的方法是drf对象,而不是Django的Httprequeset对象 2.视图方法可以返回drf的Response对象,视图会为响应数据设置 符合前端期望要求的格式 3.django的view所有异常都会以html格式显示 apiview会自动根据客户端的accept进行错误信息的格式转换 4.重新声明了一个新的as_view方法并在dispaych()进行路由分发前,会对请求的客户端进行身份认证,权限检查,流量控制
操作:
from rest_framework import serializers from app01.models import Book class ApiSerializers(serializers.ModelSerializer): class Meta: model = Book fields= "__all__" def validate_title(self,data): print("data",data) if data == "go2": raise serializers.ValidationError(detail="包含敏感字符", code="name") return data
import json from rest_framework import status from django.shortcuts import render from rest_framework.views import APIView from app01.models import Book from demo.serailizers import ApiSerializers from rest_framework.response import Response # Create your views here. class demo(APIView): def get(self,request): """获取所有数据信息""" # 1.获取所有书籍 book = Book.objects.all() # 2.实例化序列化器 serializers = ApiSerializers(instance=book,many=True) # serializers.is_valid() # 3.获取结果 data = serializers.data # 4.返回书籍信息 return Response(data=data,status=201) def post(self,request): """添加一条数据""" # 1.获取数据 并且实例化序列化器 serializers = ApiSerializers(data=request.data) state = serializers.is_valid(raise_exception=True) if state: serializers.save() return Response(data={"msg":"ok"}, status=201) else: return Response(data=serializers.errors) class Demo(APIView): def get(self,request,pk): """获取单挑数据""" try: data = Book.objects.get(pk=pk) except: Response(status=status.HTTP_404_NOT_FOUND) # 序列化 serializers = ApiSerializers(instance=data) return Response(serializers.data,status=201) def put(self,request,pk): """更新一条数据""" # 1.获取要修改的pk值 try: data = Book.objects.get(pk=pk) except: Response(status=status.HTTP_404_NOT_FOUND) # 2.查询出要改的值 serializers = ApiSerializers(instance=data,data=request.data) # 3.反序列化 serializers.is_valid(raise_exception=True) serializers.save() # 4.返回结果 return Response(serializers.data,status=status.HTTP_200_OK) def delete(self,request,pk): """删除一条数据""" pass
"""drf URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.2/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path,include,re_path from demo import views urlpatterns = [ path('demo/', views.demo.as_view()), re_path('^demo/(?P<pk>\d+)$',views.Demo.as_view()) ]
2.GenericAPIView
resr_framework.generics.GenericAPIview
继承APIview,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类提供方法支持,通常在使用时,可搭配一个或多个Mixin扩展类