序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型 反序列化,完成数据校验功能
Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer 先创建一个新的子应用sers
python manage.py startapp sers已有了一个数据库模型类students/Student
from django.db import models # Create your models here. class Student(models.Model): # 模型字段 name = models.CharField(max_length=100,verbose_name="姓名",help_text="提示文本:账号不能为空!") sex = models.BooleanField(default=True,verbose_name="性别") age = models.IntegerField(verbose_name="年龄") class_null = models.CharField(max_length=5,verbose_name="班级编号") description = models.TextField(verbose_name="个性签名") class Meta: db_table="tb_student" verbose_name = "学生" verbose_name_plural = verbose_name想为这个模型类提供一个序列化器,可以定义如下:
from rest_framework import serializers # 声明序列化器,所有的序列化器都要直接或者间接继承于 Serializer # 其中,ModelSerializer是Serializer的子类,ModelSerializer在Serializer的基础上进行了代码简化 class StudentSerializer(serializers.Serializer): """学生信息序列化器""" # 需要进行数据转换的字段 id = serializers.IntegerField() name = serializers.CharField() age = serializers.IntegerField() sex = serializers.BooleanField() description = serializers.CharField()注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。 serializer是独立于数据库之外的存在。
常用字段类型:
字段字段构造方式BooleanFieldBooleanField()NullBooleanFieldNullBooleanField()CharFieldCharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)EmailFieldEmailField(max_length=None, min_length=None, allow_blank=False)RegexFieldRegexField(regex, max_length=None, min_length=None, allow_blank=False)SlugFieldSlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+URLFieldURLField(max_length=200, min_length=None, allow_blank=False)UUIDFieldUUIDField(format=‘hex_verbose’) format: 1) 'hex_verbose’如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) ‘hex’ 如 “5ce0e9a55ffa654bcee01238041fb31a” 3)‘int’ - 如: “123456789012312313134124512351145145114” 4)‘urn’ 如: “urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a”`IPAddressFieldIPAddressField(protocol=‘both’, unpack_ipv4=False, **options)IntegerFieldIntegerField(max_value=None, min_value=None)FloatFieldFloatField(max_value=None, min_value=None)DecimalFieldDecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置DateTimeFieldDateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)DateFieldDateField(format=api_settings.DATE_FORMAT, input_formats=None)TimeFieldTimeField(format=api_settings.TIME_FORMAT, input_formats=None)DurationFieldDurationField()ChoiceFieldChoiceField(choices) choices与Django的用法相同MultipleChoiceFieldMultipleChoiceField(choices)FileFieldFileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)ImageFieldImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)ListFieldListField(child=, min_length=None, max_length=None)DictFieldDictField(child=)选项参数:
参数名称作用max_length最大长度min_length最小长度allow_blank是否允许为空trim_whitespace是否截断空白字符max_value最大值min_value最小值通用参数:
参数名称说明read_only表明该字段仅用于序列化输出,默认Falsewrite_only表明该字段仅用于反序列化输入,默认Falserequired表明该字段在反序列化时必须输入,默认Truedefault反序列化时使用的默认值allow_null表明该字段是否允许传入None,默认Falsevalidators该字段使用的验证器error_messages包含错误编号与错误信息的字典label用于HTML展示API页面时,显示的字段名称help_text用于HTML展示API页面时,显示的字段帮助提示信息Serializer的构造方法为:
Serializer(instance=None, data=empty, **kwarg)说明: 1)序列化时,将模型类对象传入instance参数 2)反序列化时,将要被反序列化的数据传入data参数 3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如
serializer = AccountSerializer(account, context={'request': request})通过context参数附加的数据,可以通过Serializer对象的context属性获取。
序列化器的使用分两个阶段: 在客户端请求时,使用序列化器可以完成对数据的反序列化。 在服务器响应时,使用序列化器可以完成对数据的序列化。
使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。 在获取反序列化的数据前,必须调用is_valid() 方法进行验证,验证成功返回True,否则返回False。 验证失败,可以通过序列化器对象的errors 属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。 验证成功,可以通过序列化器对象的validated_data属性获取数据。 在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。
定义序列化器,代码:
from rest_framework import serializers class StudentSerializer(serializers.Serializer): # 需要转换的字段声明 # 小括号里面声明主要提供给反序列化使用的 name = serializers.CharField(required=True, max_length=20) age = serializers.IntegerField(max_value=150, min_value=0,required=True) sex = serializers.BooleanField(default=True) description = serializers.CharField(required=False,allow_null=True, allow_blank=True) #required=False,字段都可以不传递给后端,allow_null=True,允许提交过来的数据为空值(null--None),allow_blank=True 允许提交过来的数据为空字符串通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进而进行验证
# 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) serializer.errors #查看错误信息 # 当验证失败时,可以直接通过声明 raise_exception=True 让django直接跑出异常,那么验证出错之后,直接就再这里报错,程序中断了就 result = serializer.is_valid(raise_exception=True) print( "验证结果:%s" % result ) # 获取通过验证后的数据 print( serializer.validated_data ) # form -- clean_data # 保存数据 student = Student.objects.create( name=serializer.validated_data.get("name"), age=serializer.validated_data.get("age"), sex=serializer.validated_data.get("sex") ) print(student) # 返回响应结果给客户端 # alt + enter,可以实现快速导包 return JsonResponse({"message": "ok"})is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
raise_exception参数 等于True会主动抛异常
serializer.is_valid(raise_exception=True)全局钩子(validate)和局部钩子(validate_ )的使用
class StudentSerizlizer(serializers.Serializer): # <QueryDict: {'name': ['c777'], 'age': ['6'], 'description': ['123'], 'class_null': ['1']}> name = serializers.CharField(max_length=4,validators=[check666,]) age = serializers.IntegerField(max_value=18) class_null = serializers.CharField() # description = serializers.CharField(required=False,allow_null=True) # required=False,allow_null=True允许字段为空,也就是不用传递过来这个data description = serializers.CharField(allow_blank=True) #allow_blank=True 允许只为空字符串 # 局部钩子:针对单个属性对应的数据进行校验 def validate_name(self,val): # print('xxxxx>>>',val) #xxxxx>>> ccbb if '777' in val: raise serializers.ValidationError('不能有777') return val #如果没有错误,需要return这个属性数据 # 全局钩子: 主要是针对多个属性数据进行校验 def validate(self,data): print(data) #OrderedDict([('name', 'c778'), ('age', 6), ('class_null', '1'), ('description', '123')]) age = data.get('age') class_null = data.get('age') if age == class_null: raise serializers.ValidationError('age和class——null不能相等') return data #如果没有错误,全局钩子要return所有数据视图部分
def post(self,request): # print(request.POST) data = { 'name':request.POST.get('name'), 'age':request.POST.get('age'), 'class_null':request.POST.get('class_null'), 'description':request.POST.get('description'), } ser = StudentSerizlizer(data=data) if ser.is_valid(): print(request.body) ret = models.Student.objects.create( **ser.validated_data ) serializer = StudentSerizlizer(instance=ret) print(serializer.data) #得到的是教研成功之后的所有正确数据 return JsonResponse(serializer.data,safe=False,json_dumps_params={'ensure_ascii':False}) # return JsonResponse({'xx':'xx'}) else: return JsonResponse({'error':'有字段错误'})执行顺序如下
# is_valid()方法时,先校验序列化器类中的所有属性Field(CharField(参数))参数对应的校验规则 # 再执行局部钩子 # 举例:比如有name和age两个属性,先执行name 的参数校验,在执行name的局部钩子(validate_name(self,val)),然后再执行age属性的参数校验,再执行age的局部钩子,最后所有属性的参数校验和局部钩子校验完成之后,执行全局钩子 # 最后执行全局钩子视图部分
from django.shortcuts import render from django.views import View # Create your views here. from students import models from .serializers import StudentSerizlizer from django.http import JsonResponse class StudentView(View): def get(self,request): all = models.Student.objects.all() serializer = StudentSerizlizer(instance=all, many=True) return JsonResponse(serializer.data, safe=False, json_dumps_params={'ensure_ascii':False}) def post(self,request): print(request.POST) data = { 'name':request.POST.get('name'), 'sex':request.POST.get('sex'), 'age':request.POST.get('age'), 'class_null':request.POST.get('class_null'), 'description':request.POST.get('description'), } serializer = StudentSerizlizer(data=data) serializer.is_valid() print(serializer.errors) print('正确数据:',serializer.validated_data) return JsonResponse({'xx':'xx'})模型类序列化器来快速创建一个Serializer类。 ModelSerializer与常规的Serializer相同,但提供了:
基于模型类自动生成一系列字段基于模型类自动为Serializer生成validators,比如unique_together包含默认的create()和update()的实现定义如下的类
from rest_framework import serializers from students import models class StudentModelSerializer(serializers.ModelSerializer): class Meta: model = models.Student fields = '__all__' # fields = ['id', 'name', 'age'] # fields = ['id', 'name', 'age'] # exclude = ['name','age'] extra_kwargs = { 'id':{'read_only':True,}, 'age':{'write_only':True,} } ''' id name = models.CharField(max_length=100,verbose_name="姓名",help_text='提示文本:不能为空') sex = models.BooleanField(default=1,verbose_name="性别") age = models.IntegerField(verbose_name="年龄") class_null = models.CharField(max_length=5,verbose_name="班级编号") description = models.TextField(max_length=1000,verbose_name="个性签名") ''' ''' id = serializers.IntegerField(read_only=True) name = serializers.CharField(max_length=6,) # name char(6) age = serializers.IntegerField(max_value=18,write_only=True) sex = serializers.BooleanField() class_null = serializers.CharField() description = serializers.CharField(allow_blank=True) '''视图当中使用
from django.shortcuts import render from django.http import JsonResponse # Create your views here. from django.views import View from .serializers import StudentModelSerializer from students import models class StudentView(View): def get(self,request): all = models.Student.objects.all() model_ser = StudentModelSerializer(instance=all,many=True) print() return JsonResponse(model_ser.data, safe=False, json_dumps_params={'ensure_ascii':False}) def post(self,request): print(request.POST) obj = StudentModelSerializer(data=request.POST) if obj.is_valid(): print(obj.validated_data) obj.save() #自动能够帮我们进行数据保存 return JsonResponse({'msg':'success'}) print(obj.errors) print(obj.validated_data) return JsonResponse({'xx':'ssssss'})drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作。所以在django原有的django.views.View类基础上,drf封装了多个子类以供使用。 Django REST framwork 提供的视图的主要作用:
控制序列化器的执行(检验、保存、转换数据)控制数据库查询的执行调用请求类和响应类APIView视图简单使用
view.py
from django.shortcuts import render # Create your views here. from django.shortcuts import HttpResponse from django.views import View from rest_framework.views import APIView from rest_framework.response import Response """drf提供的请求和响应类只能在drf封装过的子视图类中使用,也就是说不能再django.view.View中使用 只要类视图直接或者间接继承了APIView,则视图方法中使用的request,就是rest_framework.request.Request,同时,只有在APIVIew的子视图类中才可以使用rest_framework.respone.Response """ class StudentAPIView(APIView): # class StudentAPIView(View): #之前的写法 def get(self,request): print(request) #<rest_framework.request.Request object at 0x11d733e90> return Response({'msg':'ok'}) # return HttpResponse('ok')urls.py
from django.urls import path from . import views urlpatterns = [ path(r'students/',views.StudentAPIView.as_view()), ]总路由中:
from django.contrib import admin from django.urls import path,include urlpatterns = [ ... path('req/',include('req.urls')), ]启动项目,用Postman访问看到如下效果:
1).data
request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST和 request.FILES属性,但提供如下特性:
包含了解析之后的文件和非文件数据包含了对POST、PUT、PATCH请求方式解析后的数据利用了REST framework的parsers解析器,不仅支持表单类型数据(urlencoded,form-data),也支持JSON数据(application/json)2).query_params
request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。
response的方法的相关参数
Response(data, status=None, template_name=None, headers=None, content_type=None)参数说明:
data: 为响应准备的序列化处理后的数据;status: 状态码,默认200;template_name: 模板名称,如果使用HTMLRenderer 时需指明;就是有些人觉得Response返回的那个页面丑,那么就可以通过这个模板自行定制。headers: 用于存放响应头信息的字典;比如放一些cookie啊或者一些自定制的响应头啊都可以,例如:return Response({‘msg’: ‘ok’},status=204,headers={‘xx’:‘oo’})content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据(accept请求头)来设置该参数。所有状态码
HTTP_100_CONTINUE = 100 HTTP_101_SWITCHING_PROTOCOLS = 101 HTTP_200_OK = 200 HTTP_201_CREATED = 201 HTTP_202_ACCEPTED = 202 HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203 HTTP_204_NO_CONTENT = 204 HTTP_205_RESET_CONTENT = 205 HTTP_206_PARTIAL_CONTENT = 206 HTTP_207_MULTI_STATUS = 207 HTTP_208_ALREADY_REPORTED = 208 HTTP_226_IM_USED = 226 HTTP_300_MULTIPLE_CHOICES = 300 HTTP_301_MOVED_PERMANENTLY = 301 HTTP_302_FOUND = 302 HTTP_303_SEE_OTHER = 303 HTTP_304_NOT_MODIFIED = 304 HTTP_305_USE_PROXY = 305 HTTP_306_RESERVED = 306 HTTP_307_TEMPORARY_REDIRECT = 307 HTTP_308_PERMANENT_REDIRECT = 308 HTTP_400_BAD_REQUEST = 400 HTTP_401_UNAUTHORIZED = 401 HTTP_402_PAYMENT_REQUIRED = 402 HTTP_403_FORBIDDEN = 403 HTTP_404_NOT_FOUND = 404 HTTP_405_METHOD_NOT_ALLOWED = 405 HTTP_406_NOT_ACCEPTABLE = 406 HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407 HTTP_408_REQUEST_TIMEOUT = 408 HTTP_409_CONFLICT = 409 HTTP_410_GONE = 410 HTTP_411_LENGTH_REQUIRED = 411 HTTP_412_PRECONDITION_FAILED = 412 HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413 HTTP_414_REQUEST_URI_TOO_LONG = 414 HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415 HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416 HTTP_417_EXPECTATION_FAILED = 417 HTTP_418_IM_A_TEAPOT = 418 HTTP_422_UNPROCESSABLE_ENTITY = 422 HTTP_423_LOCKED = 423 HTTP_424_FAILED_DEPENDENCY = 424 HTTP_426_UPGRADE_REQUIRED = 426 HTTP_428_PRECONDITION_REQUIRED = 428 HTTP_429_TOO_MANY_REQUESTS = 429 HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431 HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451 HTTP_500_INTERNAL_SERVER_ERROR = 500 HTTP_501_NOT_IMPLEMENTED = 501 HTTP_502_BAD_GATEWAY = 502 HTTP_503_SERVICE_UNAVAILABLE = 503 HTTP_504_GATEWAY_TIMEOUT = 504 HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505 HTTP_506_VARIANT_ALSO_NEGOTIATES = 506 HTTP_507_INSUFFICIENT_STORAGE = 507 HTTP_508_LOOP_DETECTED = 508 HTTP_509_BANDWIDTH_LIMIT_EXCEEDED = 509 HTTP_510_NOT_EXTENDED = 510 HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511用于自定制浏览器的响应页面,了解
定制响应头键值对
return Response({'xx':'xxxxx'}, status=status.HTTP_201_CREATED,headers={'xx':'oo'})