eighth_序列化及其视图
2.序列化器的使用:
2.1 在客户端请求时,使用序列化器完成数据的反序列化(把字节序列恢复为对象的过程称为对象的反序列化)
2.2 在服务器响应时,使用序列器可以完成对数据的序列化(把对象转换为字节序列的过程称为对象的序列化)
2.3 数据验证
使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。
验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。
如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
验证成功,可以通过序列化器对象的**validated_data**属性获取数据。
相关代码,结合上一章
# 创建一个unsers python manage.py startapp unsers # 创建serializer 序列化器(即一个py文件) from rest_framework import serializers from students.models import Student def check_age(age): # 该方法比较少用,限制年龄不可为50 if age == 50: raise serializers.ValidationError("年龄不能刚好是50") return age class StudentSerializer(serializers.Serializer): # 需要转换的字段声明 # 小括号里面声明主要提供给反序列化使用的 id = serializers.IntegerField(read_only=True) # 只读时可调用 name = serializers.CharField(required=True, max_length=20) age = serializers.IntegerField(max_value=150, min_value=0, required=True, validators=[check_age]) sex = serializers.BooleanField(default=True, write_only=True) description = serializers.CharField(required=True, allow_null=True, allow_blank=True) # 可为空 # 如果序列化器调用的模型中的字段声明,则需要声明Meta类 # 验证 # 序列化器中可以自定义单个字段的验证方法 def validate_<字段名>(用户提交的字段数据): def validate_name(self, data): if (data == "老男孩"): raise serializers.ValidationError("用户名不能是老男孩") # 验证完成以后务必要返回字段值 return data # 方法名时固定的,用于验证多个字段,参数就是实例化序列化器类时的data参数 def validate(self, data): name = data.get("name") if (name == "python"): raise serializers.ValidationError("用户名不能是python") age = data.get("age") if (age == 0): raise serializers.ValidationError("年龄不能是0") # 验证完成以后务必要返回data return data # 添加和更新代码 # 序列化器中会提供了两个方法: create 和 update,方法名是固定的 def create(self, validated_data): # validated_data 参数,在序列化器调用时,会自动传递验证完成以后的数据 student = Student.objects.create( name=self.validated_data.get("name"), age=self.validated_data.get("age"), sex=self.validated_data.get("sex") ) return student def update(self, instance, validated_data): """更新学生信息""" instance.name = validated_data.get("name") instance.sex = validated_data.get("sex") instance.age = validated_data.get("age") instance.description = validated_data.get("description") # 调用模型的save更新保存数据 instance.save() return instance
# 视图py文件 # Create your views here. from django.http import JsonResponse from django.views import View from .serializers import StudentSerializer from students.models import Student class StudentView(View): def post(self, request): """添加一个学生""" # 接受参数 post_data = request.POST data = { "name": post_data.get('name'), "age": post_data.get('age'), "sex": post_data.get('sex'), "description": post_data.get('description'), } # 调用序列化器进行反序列化验证和转换 serializer = StudentSerializer(data=data) # 当验证失败时,可以直接通过声明 raise_exception=True 让django直接跑出异常 result = serializer.is_valid(raise_exception=True) # 1. 先使用字段声明的验证选项 # 2. 使用validate_<字段>和validate() # 3. 使用字段选项中的validators执行外部函数的验证 print("验证结果:%s" % result) # 获取通过验证后的数据 print(serializer.validated_data) # 保存数据 # student = Student.objects.create( # name=serializer.validated_data.get("name"), # age=serializer.validated_data.get("age"), # sex=serializer.validated_data.get("sex") # ) # 调用序列化器中的save方法,save会自动调用create student = serializer.save() print(student) # 返回响应结果给客户端 # alt + enter,可以实现快速导包 return JsonResponse({"message": "ok"}) def put(self, request): """更新学生信息""" # 接受参数 data = { "id": 9, "name": "abc", "age": 18, "sex": 1, } # 获取要修改的数据 instance = Student.objects.get(pk=data.get("id")) # 调用序列化器 serializer = StudentSerializer(instance=instance, data=data, partial=True) # 验证 serializer.is_valid(raise_exception=True) # 转换成模型数据 student = serializer.save() return JsonResponse({"message": "ok"}) def get(self, request): # 获取所有数据 data_list = Student.objects.all() # 使用序列化器进行序列化器 serializer = StudentSerializer(instance=data_list, many=True) # 返回数据给客户端 return JsonResponse(serializer.data, safe=False)
# unsers里的urls from django.urls.conf import path from . import views urlpatterns = [ path(r"student/", views.StudentView.as_view()), ] # 主urls urlpatterns = [ ..... path("unser/", include("unsers.urls")), ]
3.模型类序列化器
ModelSerializer与常规的Serializer相同,但提供了:
-
基于模型类自动生成一系列字段
-
基于模型类自动为Serializer生成validators,比如unique_together
-
包含默认的create()和update()的实现
代码部分
# serializer from rest_framework import serializers from students.models import Student class StudentModelSerializer(serializers.ModelSerializer): # 额外字段声明,必须在fields里面也要声明上去,否则序列化器不会调用 # password2 = serializers.CharField(write_only=True,required=True) # 如果模型类序列化器,必须声明本次调用是哪个模型,模型里面的哪些字段 class Meta: model = Student # fields = ["id","name","age","description","sex","password2"] fields = ["id", "name", "age", "description", "sex"] # fields = "__all__" # 表示操作模型中的所有字段 # 添加额外的验证选项 extra_kwargs = { "sex": {"write_only": True, }, "id": {"read_only": True, } } # 验证代码 def validate_name(self, data): if (data == "老男孩"): raise serializers.ValidationError("用户名不能是老男孩") # 验证完成以后务必要返回字段值 return data # 也可以重新声明一个create和update
# view里 from django.views import View from students.models import Student from .serializers import StudentModelSerializer from django.http.response import JsonResponse class StudentView(View): def get(self, request): # 获取数据 data_list = Student.objects.all() # 调用序列化器 serializer = StudentModelSerializer(instance=data_list, many=True) # 响应数据 return JsonResponse(serializer.data, safe=False) def post(self, request): data = { "name": "老男孩", "age": 18, "sex": 1, } # 调用序列化器 serializer = StudentModelSerializer(data=data) # 验证 serializer.is_valid(raise_exception=True) # 转换成模型数据 student = serializer.save() return JsonResponse({"message": "ok"})
# 副urls from django.urls.conf import path from . import views urlpatterns = [ path(r"student/", views.StudentView.as_view()) ] # 主urls urlpatterns = [ ...... path("mser/", include("msers.urls")), ]
4. 类视图
django中一共提供了两种视图:分别是函数视图[function view]和类视图[class view]。
# view """函数视图的登录功能""" # from django.http import HttpResponse # def login_form(request): # """显示登录页面""" # if request.method == "GET": # html = """ # <form method="post" action="/clsview/login_data/"> # 账号: <input type="text" name="usernane"><br><br> # 密码: <input type="password" name="password"><br><br> # <input type="submit" value="登录"> # </form> # """ # return HttpResponse(html) # # # def login_data(request): # """验证登录""" # print( request.POST ) # # return HttpResponse("登录成功") from django.http import HttpResponse from django.views import View class LoginView(View): def get(self, request): """显示登录页面""" html = """ <form method="post" action="/clsview/login_data/"> 账号: <input type="text" name="usernane"><br><br> 密码: <input type="password" name="password"><br><br> <input type="submit" value="登录"> </form> """ return HttpResponse(html) def post(self, request): """处理登录验证""" print(request.POST) return HttpResponse("登录成功") # 副urls from django.urls.conf import path from . import views # urlpatterns = [ # path(r"login_form/",views.login_form), # path(r"login_data/",views.login_data), # ] urlpatterns = [ path(r"login/", views.LoginView.as_view()), ] # 主urls urlpatterns = [ ...... path("clsview/", include("clsview.urls")), ]
5. 视图
drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作
Django REST framwork 提供的视图的主要作用:
-
控制序列化器的执行(检验、保存、转换数据)
-
控制数据库查询的执行
-
调用请求类和响应类[这两个类也是由drf帮我们再次扩展了一些功能类。
5.1 data
request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST和 request.FILES属性,但提供如下特性:
-
包含了解析之后的文件和非文件数据
-
包含了对POST、PUT、PATCH请求方式解析后的数据
-
rest_framework.response.Response
REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。
REST framework提供了
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类 'rest_framework.renderers.JSONRenderer', # json渲染器 'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器 ) }
5.4 构造方式
Response(data, status=None, template_name=None, headers=None, content_type=None)
参数说明:
-
data: 为响应准备的序列化处理后的数据;
-
status: 状态码,默认200;
-
template_name: 模板名称,如果使用HTMLRenderer 时需指明;
-
headers: 用于存放响应头信息的字典;
-
content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
5.5 状态码
1)信息告知 -1xx
2)成功 -2xx
3)重定向 -3xx
4)客户端错误 -4xx
5)服务端错误 -5xx
6. 视图基类
rest_framework.views.APIView
APIView与View
-
传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
-
视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
-
任何APIException异常都会被捕获到,并且处理成合适的响应信息;
-
在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
6.1
# 创建一个req python manage.py startapp req # view 视图 from django.http import HttpResponse from django.views import View from rest_framework.views import APIView from rest_framework.response import Response """drf提供的请求和响应类只能在drf封装过的子视图类中使用,也就是说不能在django.views.View中使用""" """只要类视图直接或者间接集成了APIView,则视图方法中使用的request,就是rest_framework.request.Request 同时,只有在APIView的子视图类中才可以使用 rest_framework.response.Response响应类 """ # 文本根式的状态码 from rest_framework import status class StudentAPIView(APIView): def get(self, request): # 获取get参数,request.query_params`与Django标准的`request.GET`相同,只是更换了更正确的名称而已 print(request.query_params) """ <QueryDict: {'name': ['API'], 'age': ['100']}> """ return Response({"message": "ok"}, status=status.HTTP_204_NO_CONTENT, headers={"COMPANY": "oldboy"}) def post(self, request): # 获取post数据,类似于Django中标准的`request.POST`和 `request.FILES`属性和一些其它属性 print(request.data) """ <QueryDict: {'name': ['小黑'], 'age': ['51'], 'sex': ['0']}> """ # 获取一个参数值,get参数的获取也是一样用户 data = request.data.get("lve") print(data) """美女""" # 获取多个参数值,get参数的获取也是一样用户 # 使用时注意,如果客户端提交的数据时json,则request会自动转换成字典数据,就不再提供getlist方法了. data = request.data.getlist("lve") print(data) # """['篮球', '睡觉', '美女']""" return Response({"message": "ok"}) """以前的django提供的类视图/函数视图,获取json数据""" import json class StudentView(View): def post(self, request): """获取post提交的json数据""" # request.POST 只能获取表单数据 # 获取json类型只能通过body来获取 data_byte = request.body data_string = data_byte.decode() # 通过json进行转换 data_dict = json.loads(data_string) print(data_dict) """{'name': 'xiaomingf', 'age': 12, 'sex': 1}""" return HttpResponse({"message": "ok"}) # 副urls from django.urls.conf import path from . import views urlpatterns = [ path(r"student/", views.StudentAPIView.as_view()), path(r"stu/", views.StudentView.as_view()), ] # 主urls urlpatterns = [ ...... path("req/", include("req.urls")), ]


浙公网安备 33010602011771号