DRF 的 版本,解析器,与序列化
DRF 的 版本,解析器,与序列化
补充 配置文件中的 类的调用:
(字符串)
v1 = ["view.xx.apth.Role","view.xx.apth.Role"]
for item in v1:
m = importlib.import_module('view.xx.apth')
cls = getattr(m,'Role')
cls()
1 版本控制
一般是全局的 配置
1 基于 参数版本控制
versioning_class = QueryParameterVersioning # 默认参数是 version
version = request.version # 获取到参数会放置在 request中
2 基于 url 版本控制
versioning_class = URLPathVersioning
url 规则 (?P < version > [v1 | v2] +)
print(request.versioning_scheme.reverse(viewname='api:user', request=request)) 这里可以通过request.versioning_scheme.reverse 进行url 反向解析
>> http: // 127.0.0.1: 8000 / api / v2 / user /
3 基于 host域名 版本控制
versioning_class = HostNameVersioning
http: // v1.bpple.com: 8000 / api / user /
4 当然 可以 配置到 全局中 和 视图
'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.HostNameVersioning'
‘VERSION_PARAM’:‘version
'ALLOWED_VERSIONS':['v1','v2']
'DEFAULT_VERSION':'v1'
2 解析器
Django 的 数据解析
在 django 中,满足如下两个条件时候
1 请求头中 Content-Type : application/x-www-form-urlencoded,
2 数据格式: name=alex&age=18
request.POST 中才有值
比如 form 表单提交 满足 1,2
ajax 提交的时候也是默认 1,2 条件
当然可以定义 ajax 发送的请求头和数据格式:
headers:{'Content-Type':'application/json'}
data:JSONstringfy({name:'aaa',age:12})
这时候 后台 request.POST 中不再有数据
可以从 request.BODY 中获取数据
restfuframelwork对数据的解析 - 请求体进行解析
注意:只有使用 request.data的时候,parser对象才调用
#如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
#如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据
1 获取用户的请求
2 获取用户的请求体
3 根据用户的请求头 和 parser_classes 中支持的 parser 进行比较
4 parser对象 去请求
5 request.data
视图级别配置
class GoodsVieW(APIView):
parser_classes = [JSONParser,FormParser] #表示服务端可以解析的数据格式的种类。
def post(self,request,*args,**kwargs):
#必须要调用才能启动解析器,然后解析器先判断content-type,
#如果和解析器要解析数据的类型一致,那么开始解析返回数据。
request.data
#如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
#如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据
全局配置
全局配置,简称全配:
settings.py中:
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
]
}
3 序列化
rest_framework 序列化 -- 更好的使用queryset
对象 -->> 字符串 序列化
字符串 -->> 对象 反序列化
1 基本实现
序列化的模板
class UserSerializer(serializers.Serializer):
name = serializers.CharField()
pwd = serializers.CharField()
多个
user_list = UserInfo.objects.all()
ser = UserSerializer(user_list,many=True)
单个对象
user = UserInfo.objects.all().first()
ser = UserSerializer(user,many=False)
返回
return Response(ser.data)
2 跨表处理
serializer
class UserSerializer(serializers.Serializer):
name = serializers.CharField()
pwd = serializers.CharField()
group_id = serializers.CharField()
group_title = serializers.CharField(source='group.title')
choices = serializer.CharField(source='get_type_display')
menu_id = serializers.CharField(source='group.menu_id')
menu_name = serializers.CharField(source='group.menu.name')
model
class Menu(models.Model):
name = models.CharField(max_length=32)
class Group(models.Model):
title = models.CharField(max_length=32)
menu = models.ForeignKey(to='Menu',default='1')
class UserInfo(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
group = models.ForeignKey(to='Group')
3 ModelSerializer
基本使用
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
# fields = ('name','pwd',)
fields = '__all__'
modelserializer的嵌套
user 表的外键 group ,group的外键 menu
class MenuSerializer(serializers.ModelSerializer):
class Meta:
model = Menu
fields = '__all__'
class GroupSerializer(serializers.ModelSerializer):
menu = MenuSerializer()
class Meta:
model = Group
fields = '__all__'
class UserSerializer(serializers.ModelSerializer):
group = GroupSerializer() # 通过外键直接关联实例化的对象
class Meta:
model = UserInfo
# fields = ('name','pwd',)
fields = '__all__'
---------------------------------------------------------------------------------------------------------------
等同于
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
fields = '__all__'
depth = 2 默认是0 只有表层 ,指定深度会拿出所有的关联 | 不超过10层
补充:
1 select的显示 get _字段 _ display
serializer.CharField(source='get_user_type_display')
2 通过 SerializerMethodField() # 自定义显示字段
def get_xxx(self,row):
return row
3 # modelserializer 自动关联数据表
class UserInfoSerializer(serializers.ModelSerializer):
info = serializers.CharField(source='get_user_type_display')
roles = serializers.SerializerMethodField()
def get_roles(self,row):
return [{obj.id:obj.title} for obj in row.role.all()]
class Meta:
model = UseInfo
fields = ['id','username']
extra_kwargs = {
'group':{'source':'gourp.title'}
}
4 自定义 field 类 字段
class MyField(serializers.CharField):
def to_representation(self, value):
return '{0}***'.format(value)
class Serializer_(serializers.Serializer):
username = serializers.CharField(error_messages={'required':'请输入姓名'},validators=[MyValidator])
pwd = MyField()
5 生成连接
url(r'^api/(?P<version>[v1|v2]+)/(?P<pk>\d+)/',UserGroupView.as_view(),name='group')
class UserInfoSerializer(serializers.Serializer):
group = serializers.HyperlinkedIndentityField(view_name='group',lookup_id='group.id',lookup_url_kwarg='')
class Meta:
model = UserInfo
fields = '__all__'
class UserInfoView(APIView):
obj = UserInfo.objects.get(...)
ser = UserInfoSerializer(instance=obj,many=False,context={"request":request})
return JsonResponse(ser.data)
6 自定义validator
class MyValidator(object):
def __init__(self,base):
self.base = base
def __call__(self, value):
if not value.startswith(self.base):
msg = '情以%s 开头'% self.base
raise exceptions.ValidationError(msg, code='unique')
class Serializer_(serializers.Serializer):
username = serializers.CharField(error_messages={'blank':'请输入姓名'},validators=[MyValidator('he')])
7 自定义 钩子 validate_field
class Serializer_(serializers.Serializer):
username = serializers.CharField(error_messages={'blank':'请输入姓名'},validators=[MyValidator('he')])
pwd = serializers.CharField()
def validate_pwd(self,value):
if not value.startswith('123'):
raise exceptions.ValidationError('密码情以123开头', code='unique')
return value
{
"pwd": [
"密码情以123开头"
]
}
8 全局钩子
def validate(self, value):
if value.get('pwd') == value.get('repwd'):
return value
raise exceptions.ValidationError('两次密码不一致')
{
"non_field_errors": [
"两次密码不一致"
]
}
读书使人心眼明亮