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": "]>"
    roles = serializers.CharField(source='roles.all') # "roles": "]>"

    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('...')

你可能感兴趣的:(django_rfw_3)