django_rfw_3

本篇内容

补充:

关于实例化
v1 = ['view.xxx.path.Role','view.xxx.path.']

回顾

为什么用 django restframework?

关于认证、权限、节流,只需要写类,就可以实现他们的方法返回值就可。
它帮我们实现了一些功能。

设计好的点?

单独视图配置和全局配置, 它的全局配置类似django中间件(importlib + 反射)。
动态配置可扩展(用户下单后,通过短信、邮件等提醒)。

关于它的原理:

基于 cbv,和 django 继承的是同一个。
请求进来之后,先执行 dispatch ( 五大功能,都是在 dispatch 里面实现)。

  • 先执行 as_view()
  • view 函数
    obj = cls()
    。。。
    return self.dispatch()
  • dispatch
    • 封装 request
    • 版本
    • 认证 -> request.user -> 循环对象,执行_authticate
    • 权限
    • 节流

新 request对象(request,认证相关)

如果新 req 对象里面没有你要的东西,就去旧的 request 里面找。
request.query_params
request.POST
request.Meta

今日内容

  1. 版本,
  2. 解析器,
  3. 序列化,
  4. 分页

版本和解析器一旦配置好,基本可以不用再动。
序列化:

  • QuuerySet 类型 -> list,dict
  • 请求验证
    django form 组件也可以用在 restframework。

1. 为什么要有版本?

如果是version_1,就返回111
如果是version_2,就返回22
如果是version_3,就返回3
自己可以在 url 里面写,然后 request 获取再判断就可以。

但是d_rfw 已经帮你做好了。
from rest_framework.versioning
versioning_class = QueryParameterVersioning # 这个就是帮你获取 version 的值。
推荐:
versioning_class = UrlPathVersioning

版本源码执行流程
1. 进来先到 dispatch()
   def dispatch(self, request, *args, **kwargs):
2. self.initial(request, *args, **kwargs)
3.  # 处理版本信息
    # 这两句是处理版本信息,点击self.determine_version
      version, scheme = self.determine_version(request, *args, **kwargs)
      request.version, request.versioning_scheme = version, scheme
4. def determine_version(self, request, *args, **kwargs):
       if self.versioning_class is None:
          return (None, None)
       scheme = self.versioning_class()
       return (scheme.determine_version(request, *args, **kwargs), scheme)
5. URLPathVersioning.determine_version(self, request, *args, **kwargs):
   return version
6. 封装到 request 中
   request.version, request.versioning_scheme = version, scheme
7. 使用
   class URLPathVersion(APIView):
  # 关于 urlpath
  versioning_class = URLPathVersioning

  def get(self,request,*args,**kwargs):
      print(request.version)
      print(request.versioning_scheme)

2. 解析器

解析器对请求的数据解析
d_rdw 是针对请求头解析。

request.POST 不一定拿得到值,这个和 Content_Type 有关。

  • Content_Type : application/url-encoding

    • 以这个发送的话,post 和 body 里面都会有值。
    • 弊端:只有在 body 里可以拿到Bytes 类型的变态大叔。
  • d_rdw: parse_classes = [JONParse ,FormDataParse]

  • 最常用的即 JSONParse
    解析器小总结:

    • 何时执行? 只有执行 request.data/request.FILES/reqeust.POST
      • 根据 content_type头,判断是否支持。
2. rest framework解析器
        请求的数据进行解析:请求体进行解析。表示服务端可以解析的数据格式的种类。
        
            Content-Type: application/url-encoding.....
            request.body
            request.POST
            
            Content-Type: application/json.....
            request.body
            request.POST
        
        客户端:
            Content-Type: application/json
            '{"name":"alex","age":123}'
        
        服务端接收:
            读取客户端发送的Content-Type的值 application/json
            
            parser_classes = [JSONParser,]
            media_type_list = ['application/json',]
        
            如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
            如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据
        
        
        配置:
            单视图:
            class UsersView(APIView):
                parser_classes = [JSONParser,]
                
            全局配置:
                REST_FRAMEWORK = {
                    'VERSION_PARAM':'version',
                    'DEFAULT_VERSION':'v1',
                    'ALLOWED_VERSIONS':['v1','v2'],
                    # 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"
                    'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
                    'DEFAULT_PARSER_CLASSES':[
                        'rest_framework.parsers.JSONParser',
                        'rest_framework.parsers.FormParser',
                    ]
                }

3. 序列化 重点!!!

这 tm 是什么?
- 序列化: 对象 --> 字符串,
- 反序列化: 字符串 --> 对象。
- 目前学过的:json/pickle

restful 序列化 存在的意义:
- 就是为了解决 QuerySet 的序列化问题。

models.py

from django.db import models

# Create your models here.

class Menu(models.Model):
    name = models.CharField(max_length=32)

class Group(models.Model):
    title = models.CharField(max_length=32)
    mu = 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')
    roles = models.ManyToManyField(to='Role')


class Role(models.Model):
    name = models.CharField(max_length=32)

复杂序列化
views.py

a. 复杂序列化
解决方案一:
class MyCharField(serializers.CharField):
    def to_representation(self, value):
        data_list = []
        for row in value:
            data_list.append(row.name)
        return data_list


class UsersSerializer(serializers.Serializer):
    name = serializers.CharField()  # obj.name
    pwd = serializers.CharField()  # obj.pwd
    group_id = serializers.CharField()  # obj.group_id
    xxxx = serializers.CharField(source="group.title")  # obj.group.title
    x1 = serializers.CharField(source="group.mu.name")  # obj.mu.name
    # x2 = serializers.CharField(source="roles.all") # obj.mu.name
    x2 = MyCharField(source="roles.all")  # obj.mu.name


解决方案二:
class MyCharField(serializers.CharField):
    def to_representation(self, value):
        return {'id': value.pk, 'name': value.name}


class UsersSerializer(serializers.Serializer):
    name = serializers.CharField()  # obj.name
    pwd = serializers.CharField()  # obj.pwd
    group_id = serializers.CharField()  # obj.group_id
    xxxx = serializers.CharField(source="group.title")  # obj.group.title
    x1 = serializers.CharField(source="group.mu.name")  # obj.mu.name
    # x2 = serializers.CharField(source="roles.all") # obj.mu.name
    x2 = serializers.ListField(child=MyCharField(), source="roles.all")  # obj.mu.name


这是复杂序列化的第三种方法,也是极力推荐的方法   *************
class UserSerializer(serializers.Serializer):
    name = serializers.CharField()     # obj.name
    pwd = serializers.CharField()       # obj.pwd
    group_id = serializers.CharField()  # obj.group_id
    g_title = serializers.CharField(source='group.title')   # obj.group.title
    g_mu_name = serializers.CharField(source='group.mu.name') # obj.group.name

    # M2M,这样写的话,只能拿到 对象
    # roles = serializers.CharField(source='roles.all') # "roles": "<QuerySet [<Role: Role object>]>"
    roles = serializers.CharField(source='roles.all') # "roles": "<QuerySet [<Role: Role object>]>"

    xx = serializers.SerializerMethodField()
    def get_xx(self,obj):
        role_list = obj.roles.all()
        data_list = []
        for role_obj in role_list:
            data_list.append({'pk':role_obj.pk,'name':role_obj.name,})
        return data_list


不管哪种方法,都走这个视图
class UserView(APIView):
    def get(self,request,*args,**kwargs):
        self.dispatch
        # 方式一:用我们之前最简单粗暴的方法。
        # user_list = models.UserInfo.objects.all().values('name','pwd','group_id','group__title','group__mu__name')
        # return Response(user_list)

        # 方式二:多对象
        user_list = models.UserInfo.objects.all()
        # print(user_list)
        # obj = user_list.first()
        # o_name = obj.roles.all()
        # for i in o_name:
        #     print(i.name)
        ser = UserSerializer(instance=user_list,many=True)
        return Response(ser.data)

b. 基于 model。   在序列化里面继承了 ModelSerializer类
class PasswordValidator(object):
    def __init__(self, base):
        self.base = base

    def __call__(self, value):
        if value != self.base:
            message = '用户输入的值必须是 %s.' % self.base
            raise serializers.ValidationError(message)

    def set_context(self, serializer_field):
        """
        This hook is called by the serializer instance,
        prior to the validation call being made.
        """
        # 执行验证之前调用,serializer_fields是当前字段对象
        pass

#  注意这里继承的类:ModelSerializer
class UsersSerializer(serializers.ModelSerializer):
    x = serializers.CharField(source='name')
    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['name', 'pwd', 'x', 'group'] # 自定义字段时候要注意指定 source,source里面的数据必须是数据库有的。
        extra_kwargs = {
            'name': {'min_length': 6},
            'pwd': {'validators': [PasswordValidator(666), ]}}



# 使用
class UsersView(APIView):
    def get(self,request,*args,**kwargs):
        # self.dispatch
        user_list = models.UserInfo.objects.all()
        # [obj1,obj2,obj3]
        # 序列化。
        ser = UsersSerializer(instance=user_list,many=True,context={'request':request})
        return Response(ser.data)

    def post(self,request,*args,**kwargs):
        # 验证:对请求发来的数据进行验证。
        ser = UsersSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)
        return Response('...')



c. 生成 url
class Users_Serializer(serializers.ModelSerializer):
    group = serializers.HyperlinkedIdentityField(view_name='detail')
    class Meta:
        model = models.UserInfo
        fields = '__all__'
        extra_kwargs = {
            'user': {'min_length': 6},
            'pwd': {'validators': [PasswordValidator(666),]}
        }

class Users_View(APIView):
    def get(self, request, *args, **kwargs):
        # 序列化,将数据库查询字段序列化为字典
        data_list = models.UserInfo.objects.all()
        ser = Users_Serializer(instance=data_list, many=True, context={'request': request})
        # 或
        # obj = models.UserInfo.objects.all().first()
        # ser = UserSerializer(instance=obj, many=False)
        return Response(ser.data)

    def post(self, request, *args, **kwargs):
        # 验证,对请求发来的数据进行验证
        print(request.data)
        ser = Users_Serializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)

        return Response('POST请求,响应内容')



d. 自动生成 url    继承该类: HyperlinkedModelSerializer

class UsersSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"
        # fields = ['id','name','pwd']

    class UsersView(APIView):
        def get(self,request,*args,**kwargs):
            self.dispatch
            # 方式一:
            # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
            # return Response(user_list)

            # 方式二之多对象
            user_list = models.UserInfo.objects.all()
            # [obj1,obj2,obj3]
            ser = UsersSerializer(instance=user_list,many=True,context={'request':request})
            return Response(ser.data)



e. 关于请求数据验证
# 第一种:
class PasswordValidator(object):
    def __init__(self, base):
        self.base = base

    def __call__(self, value):
        if value != self.base:
            message = '用户输入的值必须是 %s.' % self.base
            raise serializers.ValidationError(message)

    def set_context(self, serializer_field):
        """
        This hook is called by the serializer instance,
        prior to the validation call being made.
        """
        # 执行验证之前调用,serializer_fields是当前字段对象
        pass


class UsersSerializer(serializers.Serializer):
    name = serializers.CharField(min_length=6)
    pwd = serializers.CharField(error_messages={'required': '密码不能为空'}, validators=[PasswordValidator('666')])


# 第二种
class PasswordValidator(object):
    def __init__(self, base):
        self.base = base

    def __call__(self, value):
        if value != self.base:
            message = '用户输入的值必须是 %s.' % self.base
            raise serializers.ValidationError(message)

    def set_context(self, serializer_field):
        """
        This hook is called by the serializer instance,
        prior to the validation call being made.
        """
        # 执行验证之前调用,serializer_fields是当前字段对象
        pass


class UsersSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"
        extra_kwargs = {
            'name': {'min_length': 6},
            'pwd': {'validators': [PasswordValidator(666), ]}
        }


使用:
class UsersView(APIView):
    def get(self, request, *args, **kwargs):
        self.dispatch
        # 方式一:
        # user_list = models.UserInfo.objects.all().values('name','pwd','group__id',"group__title")
        # return Response(user_list)

        # 方式二之多对象
        user_list = models.UserInfo.objects.all()
        # [obj1,obj2,obj3]
        ser = UsersSerializer(instance=user_list, many=True, context={'request': request})
        return Response(ser.data)

    def post(self, request, *args, **kwargs):
        ser = UsersSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)
        return Response('...')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • Refer to: www.threemeal.com/blog/12/ 中间件 中间件是一个钩子框架,它们可以介...
    兰山小亭阅读 16,477评论 9 165
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,936评论 6 13
  • 一杯咖啡 被晨起的勺子搅拌 我仍困意未消,衣衫不整 旁边飘着刚熄灭的香烟氤氲 衬着我的愁容 一粒冰糖 落杯中 依稀...
    爱风城阅读 400评论 2 10
  • 近日,花舞人间对新津、眉山等地免费,趁着星期天,小游一番。 早已不是杜鹃花开的时节,荷花也渐渐败了,只有走马观花,...
    星星嗦阅读 241评论 0 0