Fork me on GitHub

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": [
        "两次密码不一致"
    ]
}
posted @ 2018-03-02 19:38  派对动物  阅读(1097)  评论(0编辑  收藏  举报
Top