django-rest 版本,解析器,序列化, 分页版本,路由、渲染

序列化, 分页,路由,视图,渲染器,版本,解析器,

一、版本
1.自定义get传参:
通过get方式传参拿到版本,通过自定义一个类, 然后重写determine_version方法来实现,然后在视图中配置。

class ParamVersion(object):
    def determine_version(self, request, *args, **kwargs):
        # version = request._request.GET.get('version')
        version = request.query_params.get('version')
        return version

from rest_framework.versioning import BaseVersioning
class UserView(APIView):

    versioning_class = ParamVersion
    def get(self, request,*args, **kwargs):
        print(request.version)  # 这里就能拿到版本,通过get方式传参
        return HttpResponse('用户列表')

2.通过get传参用rest框架来设置版本。
a.在settings中配置

REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',  # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'], # 可支持版本
    'VERSION_PARAM': 'version', # 参数
}

b. 在view视图中

from rest_framework.versioning import QueryParameterVersioning

class UserView(APIView):
    versioning_class = QueryParameterVersioning
    def get(self, request,*args, **kwargs):
        print(request.version)
        return HttpResponse('用户列表')

3.通过url传参
a、在url中通过正则匹配

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/users/$', views.UserView.as_view()),
]

b.在视图函数中

from rest_framework.versioning import URLPathVersioning

class UserView(APIView):
    versioning_class = QueryParameterVersioning
    def get(self, request,*args, **kwargs):
        print(request.version)
        return HttpResponse('用户列表')

4.通过url
a、settings

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':['rest_framework.versioning.URLPathVersioning'],
    'DEFAULT_VERSION': 'v1',  # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'], # 可支持版本
    'VERSION_PARAM': 'version', # 参数
}

b、在视图中通过这样获取

from rest_framework.versioning import URLPathVersioning

class UserView(APIView):

    versioning_class = URLPathVersioning
    def get(self, request,*args, **kwargs):
        print(request.version)
        return HttpResponse('用户列表')

c、在url中

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/users/$', views.UserView.as_view()),
]

二、解析器
1.接收的消息有很多中,rest提供的这两种较为常用:JSONParserFormParser

from rest_framework.parsers import JSONParser,FormParser
class ParserView(APIView):
    parser_classes = [JSONParser, FormParser]
    def get(self, request, *args, **kwargs):
        """
        # JSONParser:允许用户发送JSON格式数据  对应请求头:content-type:application/json
        # FormParser: 允许用户发送表单格式数据 对应请求头:content-type:application/x-www-form-urlencoded
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        print(request.data) # 从这里面拿值
        return HttpResponse("Json 格式数据")
  1. 全局配置
    在settings中
REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': ['rest_framework.parsers.SONParser','rest_framework.parsers.FormParser']
}

然后在view中直接通过request.data 调用

3.总结:
只需要在全局做好配置就行了

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': ['rest_framework.parsers.SONParser','rest_framework.parsers.FormParser']
}

在获取值的时候用request.data中获取, 如果是上传文件,直接再在单独的视图函数中加入该配置就行了FileUploadParser

三、序列化:对请求的数据的验证,对qureyset 进行序列化。

1.数据库的内容进行序列化

# 自己简单实现
import json   
from .models import Role
class RolesView(APIView):
    def get(self, request, *args, **kwargs):
        # 方式一, 自己简单实现
        roles = Role.objects.all().values('id', 'title')
        roles = list(roles)
        ret = json.dumps(roles, ensure_ascii=False)
        return HttpResponse(ret)
# query_set 进行序列化
import json
from .models import Role
from rest_framework import serializers

# 通过rest中的序列化来实现。serializers
class RolesSerializer(serializers.Serializer):
    title = serializers.CharField()     # 这里的字段必须是模型中必须一样


class RolesView(APIView):
    def get(self, request, *args, **kwargs):
        # 方式二
        roles = Role.objects.all().values('id', 'title')
        ser = RolesSerializer(instance=roles, many=True)
        # ser.data 这是一个字典
        ret = json.dumps(ser.data, ensure_ascii=False)
        return HttpResponse(ret)

**注意:**上面是对querySet类型进行序列化的用法,如果是object…first 获取的单个对象, 那么RolesSerializer(instance=roles, many=False) 并且就不需要dumps,直接返回ser.data

如何对数据库的外键,多对多字段进行序列化,并显示自己想要的字段呢?

from . import models

class UserInfoSerializer(serializers.Serializer):
	# 这这里定义哪些字段, 就能序列化哪些字段,并返回。主要是source参数 和自定义函数
    user_type = serializers.CharField(source='get_user_type_display')  # choice字段显示中文source='get_user_type_display'
    username = serializers.CharField()
    password = serializers.CharField()
    gp = serializers.CharField(source='group.title')  # 外键group.title:结果直接显示外键组的title字段
    # rls = serializers.CharField(source='roles.all') # 模型中有多对多字段就不能使用这种方式取值显示
    rls = serializers.SerializerMethodField()  # 自定义显示多对多显示, 允许创建一个自定义的函数,如:get_rls
    
    def get_rls(self, row):
        role_obj_list = row.roles.all()
        ret = []
        for item in role_obj_list:
            ret.append({'id': item.id, 'title': item.title})
        return ret
    
class UserInfoView(APIView):
    def get(self, request, *args, **kwargs):
        # 方式二
        user = models.UserInfo.objects.all()
        ser = UserInfoSerializer(instance=user, many=True)
        ret = json.dumps(ser.data, ensure_ascii=False)
        return HttpResponse(ret)

除了上面这种方式序列化以外, rest还提供了另一种方法,搭配使用Meta model。

from . import models
class UserInfoSerializer(serializers.ModelSerializer): # 这里继承ModelSerializer
    user_type = serializers.CharField(source='get_user_type_display')  # choice字段显示中文source='get_user_type_display'
    rls = serializers.SerializerMethodField()  # 自定义显示多对多显示, 允许创建一个自定义的函数
    class Meta:  
        model = models.UserInfo
        # fields = "__all__" # 这里生成的是模型中对应的字段,但是多对多外键还是比较简单,不是汉字。
        fields = ['id', 'username', 'password', 'user_type']
        depth = 1  # 这个字段可以帮我们一层一层的取值,对外键和多对多字段使用, 数值是几那么就往后取几层。官方建议0-10之间。即自动序列化连表操作, 这样就可以不用自定义外键字段和多对多字段啦!!!
    def get_rls(self, row):
        role_obj_list = row.roles.all()
        ret = []
        for item in role_obj_list:
            ret.append({'id': item.id, 'title': item.title})
        return ret


class UserInfoView(APIView):
    def get(self, request, *args, **kwargs):
        user = models.UserInfo.objects.all()
        ser = UserInfoSerializer(instance=user, many=True)
        ret = json.dumps(ser.data, ensure_ascii=False)
        return HttpResponse(ret)

小总结:首先写序列化类,可以继承Serializer,ModelSerializer这两种,其中ModelSerializer 可以直接使用models中的自定, 如果显示不一样,可以自定制。其他:depth自动序列化连表操作, 这样就可以不用自定义外键字段和多对多字段。

补充:生成链接,可以基于HyperlinkedModelSerializer 字段来做,这里省略。

2.序列化:请求数据校验

class UserGroupSSerializer(serializers.Serializer):
    title = serializers.CharField(error_messages={'required':'标题不能为空'}) #参数校验

class UserGroupView(APIView):
    """序列化之对数据进行校验"""
    def post(self,request, *args, **kwargs):
        # print(request.data)
        ser = UserInfoSerializer(data=request.data) 
        if ser.is_valid(): # 将传过来的数据进行校验
            print(ser.validated_data)
        else:
            print(ser.errors)
        return HttpResponse('提交数据')

钩子函数自定义验证字段。

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import UserModel
class RedisSerializers(serializers.ModelSerializer):
    class Meta:
        model = UserModel
        fields = ("name", "age", "nums", "c_time")
    def validate(self, attrs):
        """自定义所以字段验证"""
        return attrs
    def validate_age(self, data):
        """通过钩子自定义字段验证,validate_[字段名称]"""
        if not data:
            raise ValidationError(detail="输入错误")
        return data

以上方法都是在serializer.is_valid(raise_exception=True)的时候通过钩子去执行,所以不需要手动执行这两个方法。

3、restframwork渲染器。

# 1. 在settings中先配置好rest_framwork应用
from rest_framework.response import Response     # 2 这一步导入Response
class PagerView(APIView):
    def get(self, *args, **kwargs):
        roles = models.Role.objects.all()
        ser = PagerSerializers(instance=roles, many=True)
        return Response(ser.data)  # 3 这里直接使用,省去我们自己json.dumps()
        # 最后访问视图, 就能在页面上看到json格式的数据,并且有样式,
  1. 分页:

简单使用
a 在settings中配置一页显示的条数

# settings
REST_FRAMEWORK = {
    'PAGE_SIZE':10, #配置每页的条数
}

#views
from api.utils.serializsers import PagerSerializers
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination


class PagerView(APIView):
    def get(self,request, *args, **kwargs):
        # 1 获取所有数据
        roles = models.Role.objects.all()
        # 2 创建分页对象
        pg = PageNumberPagination()
        # 3 在数据库中获取分页的数据
        pager_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
        # 4 对分页的数据进行序列化
        ser = PagerSerializers(instance=pager_roles, many=True)  # 只序列化获取的分页的数据
        print(pager_roles)
        return Response(ser.data)

b 自定制分页

# 1.自定制分页,继承PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
    page_size = 5   # 默认每页显示的条数
    page_size_query_param = 'size'  # 请求带size=10,表示一页显示10条数据,不再使用默认的5条数据
    max_page_size = 20 # 这里表示每页最多获取的条数
    
    page_query_param = 'page' # 这里表示页码参数 比如 page=1 表示获取第一页

class PagerView(APIView):
    def get(self,request, *args, **kwargs):
        # 1 获取所有数据
        roles = models.Role.objects.all()
        # 2 创建分页对象
        pg = MyPageNumberPagination()  # 这里使用自己的分页类,实例化
        # 3 在数据库中获取分页的数据
        pager_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
        # 4 对分页的数据进行序列化
        ser = PagerSerializers(instance=pager_roles, many=True)  # 只序列化获取的分页的数据
        # print(pager_roles)
        # pg.get_paginated_response(ser.data) 可以多返回一些参数
        # return pg.get_paginated_response(ser.data)
        return Response(pg.get_paginated_response(ser.data))

c、 LimitOffsetPagination 分页
原理同上, 只需要定制把定制的重写一下

d、CursorPagination 分页(只有上一页下一页, 加密)
原理同上, 只需要定制把定制的重写一下

5.视图
django-restframwork 视图有:APIView, 它是最接近django原生的view的。GenericAPIView它的本质跟APIView是一样的,只是将部分功能进行打包封装了一下,然后在路由中配置一下对应函数的映射关系即可(个人推荐使用这个视图和APIView)。ModelViewSet是功能比较齐全的一个view,他封装的查询集 序列化,以及分页,并且继承了增删改查的自个mixin, 如果不需要定制化内容, 完全可以使用ModelViewSet

# views
class BodyView(GenericAPIView):
    queryset = models.Role.objects.all()
    serializer_class = PagerSerializers
    pagenation_class = PageNumberPagination

    def get(self,request, *args, **kwargs):
        roles = self.get_queryset() #models.Role.objects.all()
        pager_roles = self.paginate_queryset(roles) # 分页
        ser = self.get_serializer(instance=pager_roles, many=True)
        return Response(ser.data)
# urls
urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/user/$', views.BodyView.as_view({'get':'get'})),
]

在这里插入图片描述
6. 路由,只需在urls中导入routers, 然后注册即可。

在这里插入图片描述

7.渲染器
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值