REST_FRAMEWORK重要组件--->Serializer
6.序列化器(Serializer)
- 假设有一张表格Cos,表格里面有一个title字段写角色名。利用json.dump()进行序列化。
方式一:
Class Cosview(APIview):
def get(self,request,*args,**kwargs):
cos=models.Cos.objects.all().values('id','title')
cos=list(cos)
ret=json.dumps(cos,ensure_ascii=False)
return HttpResponse(ret)
(json.dumps())只能处理Python类型的数据。
第一个cos返回的是Queryset对象,通过list转化。
方式二:
from rest_framework import serializer.Serializer
Class CosSerializer(Serializer):
title=Serializer.CharFields() #对应Cos表格字段,表格中不设id字段,系统都会自动加上去
id=Serializer.IntegerFields()
Class Cosview(APIview):
def get(self,request,*args,**kwargs):
cos=models.Cos.objects.all()
ser=CosSerializer(instance=cos,many=True) #many代表的是多条数据
ret=json.dumps(ser.data,ensure_ascii=False) #ensure_ascii=False 表示不翻译
return HttpResponse(ret)
问题回顾:
1.
- 在当初额Userinfo表格中
User_type_choice=((1,"普通用户"),(2,“VIP”),(3,"SVIP"))
- 当初在model模型中的语句
user_type=models.IntegerField(choice=User_type_choice)
- 第一个问题:用数字和中文显示用户登录时的等级。
Class UserinfoSerializer(serializer.Serializer):
1.user_type=serializer.IntegerField() #利用integer类型去序列化,回显的一定是'1,2,3'的数字
2.user_type=serializer.CharField(source='user_type') #回显的还是‘1,2,3’
3.user_type=serializer.CharField(source='get_user_type_display') #回显中文
2.
- 之前有一个Usergroup的表格,为User所在的分组,字段名为title字段,分A/B组
- 在model类中Userinfo 和Usergroup进行了一对一的连表
group=models.ForeignKey("Usergroup")
则
UserinfoSerializer(serializer.Serializer):
group=serializer.CharField(Source="group.title") #当表与表建立起连接时,可以逐层往下查
- 一对一,一对多的连表示,可以利用Source来进行指定字段。
- 当Userinfo与其他表为ManytoMany关系时,就不能用source。
roles=models.ManyToManyField("Role") #例子,人和角色之间可以多对多关系
Class UserinfoSerializer(serializer.Serializer):
roles=serializer.SerializerMethodField() #自定义显示,自定义一个以字段名为后缀的函数,
参数为(self,row)
def get_roles(self,row):
role_list=row.roles.all()
ret=[]
for item in role_list:
ret.append({'id':item.id,'title':item.title})
return ret
#Role表里面一个‘id’,一个'title',相当于作为了userinfo的外键。
ModelSerializer------>继承于Serializer
1.正常流程:
Class UserinfoSerializer(serializer.ModelSeriliazer):
user_type=serializer.CharField(source="get_user_type_display")
roles=serializer.SerializerMethodField() #自定义显示
Class Meta:
model=models.Userinfo #说明使用的是Userinfo表格
fields=['id','username','password','user_type','roles']
#fields='__all__' #即显示所有字段
def get_roles(self,row): #自定义的方法为get_mehodname
role_list=row.roles.all()
ret=[]
for item in role_list:
ret.append({'id':item.id,'title':item.title})
return ret
这里重点就是一对一、一对多、中文显示和连表查询的操作。
2.简单流程,利用depth做一个深度的权限放宽:
Class UserinfoSerializer(serializer.Serializer):
Class Meta:
model=model.Userinfo
fields='__all__'
depth=1 #depth默认为0,最大为10
depth:深度,为0表示第一层,即id层。可以显示一对多,多对多之间的关系。
ModelSerializer.Hypermedia
- Hypermedia是返回结果以链接的形式,点击链接进行url的跳转,然后触发view。
url(r'^(?p<version>[v1][v2]+)/userinfo/$',userinfo.view.as_view())
url(r'^(?p<version>[v1][v2]+)/group/(?p<pk>\d+)$',groupview.as_view()),name='gp'
Class UserinfoSerializer(seriializer.ModelSerializer):
group=Serializer.HyperlinkIdentityField(view_name='gp',lookup_field='group_id,lookup_url_kwarg='pk'')
Class Meta:
model=models.Userinfo
fields=['id','username'.'password','group','roles']
depth=0 #group返回一个链接地址对象
Class Userinfo(APIview):
def get(self,request,*args,**kwargs):
users=models.Userinfo.objects.all()
# pk=kwargs.get('pk') #可以从url中获取pk的值、然后object.filter()进行数据的筛选、
Ser=UserinfoSerializer(instance=users,many=True,Contect={'request':request})
ret=json.dumps(ser.data,ensure_ascii=False)
return HttpResponse(ret)
Serializers序列化验证(类似于表单验证)
- 表单验证
1.request.POST.get <--------> forms=forms(request.POST)
2.Django 自带的form表单是验证前段字段数据合法性的一个好途径。
3.在APP中编写form.py文件,继承forms.Form,在文件中的字段必须和前段发来的字段一致。比如:
from django.core import validators
email=Forms.CharField(validators=[validators.Emailvalidators(mess=' ')])
表单中的错误信息提示可以为:error_message={"invalid":"____"}
from django.views.generic import view
Class Index(view):
def get(self,request,*args,**kwargs):
pass
def post(self,request,*args,**kwargs):
form=form(request.POST) #将request.POST的数据放到form类中去验证、
if form.is_valid(): #如果数据验证通过了,就用相应的字段将干净的数据提取出来、
price=form.cleaned_data.get('price')
else:
print(form.error.get_json_data()) #数据类型出错,显示出错信息、
2.利用Form的实例在前端生成表格,利用context渲染html{‘form’:form},前端{{form.as_table}}。
Views
from .forms import form
Class Index(View):
def get(self,request,*args,**kwargs): #前端get请求实际上是在向服务器请求数据,所以直接将form渲染返回
return render(request,'index.html',{'form':form})
def post(self,request,*args,**kwargs):
pass
Index.html
<table>
{{form.as_table}}
<input text='submit',name='提交'>
</table>
3.Serializers序列验证
- 获取字段值,不仅可以用request._request.GET/POST.get(),也可以使用parser的request.data
Class SerializerUsergroup(serializers.Serializer):
title=Serializers.Charfield(error_message={'required':'标题不能为空'})
Class Usergroupview(APIView):
def post(self,request,*args,**kwargs):
ser=SerializerUsergroup(data=request.data)
if ser.is_valid():
print(validated_data) #大致和form表单一致,利用is_valid进行判断
else:
print(ser.errors)
return HttpResponse('ok')
Serializer.CharField(除了error_message 还可以用自定义的Validators=[abcValidators('abc'),])
abcValidators类 ,自定义了类内容,必须以abc为开头的类
Class abcValidators(object):
def __init__(self,base):
self.base=base
def __call__(self,value): #value--->的值就是request.data 值
if not value.startwith(self.base):
message="标题必须以%s 开头“%self.base
raise Serializer.ValidationError(message)