Django REST framework之序列化、解析器

Demo的目录结构:

DjWebApi2.urls文件:API路由分发

"""DjWebApi2 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,include
from Api.views import demo

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('Api.urls')),
    path('demo/',demo.demo),
]

Api.url文件:API路由

from django.urls import path,re_path
from Api.views import version,parserdemo,serializersdemo

urlpatterns = [
    # 版本demo
    re_path(r'^(?P<version>[v1|v2]+)/users/$', version.UsersView.as_view(), name='userspath'),
    # 解析器demo
    re_path(r'^(?P<version>[v1|v2]+)/parser/$', parserdemo.ParserView.as_view(), name='parserpath'),
    # 序列化demo
    re_path(r'^(?P<version>[v1|v2]+)/serializers/$', serializersdemo.UserinfoView.as_view(), name='serializerspath'),
    re_path(r'^(?P<version>[v1|v2]+)/group/(?P<gid>\d+)$', serializersdemo.GroupView.as_view(), name='gp'),
    re_path(r'^(?P<version>[v1|v2]+)/usergroup/$', serializersdemo.UserGroupView.as_view()),
]

settings.py:配置文件

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning', # /api/v1/users/ 版本配置
    'DEFAULT_VERSION':'v1', # 默认版本
    'ALLOWED_VERSIONS':['v1','v2'], # 可用版本
    'VERSION_PARAM':'version', # 版本参数

    'DEFAULT_PARSER_CLASSES':[
        "rest_framework.parsers.JSONParser",  # 仅处理请求头content-type为application/json的请求体
        "rest_framework.parsers.FormParser",  # 仅处理请求头content-type为application/x-www-form-urlencoded 的请求体
        "rest_framework.parsers.MultiPartParser", # 仅处理请求头content-type为multipart/form-data的请求体
    ],
    'UNICODE_JSON': False, # 编码格式
}

version.py:版本demo

from django.shortcuts import render,HttpResponse
from django.urls import reverse
from rest_framework.views import APIView
from rest_framework.request import Request
# Create your views here.
# 自定义
# class ParamVersion(BaseVersioning):
#     def determine_version(self, request, *args, **kwargs):
#         version = request.query_params.get('version')
#         return version


class UsersView(APIView):

    def get(self,request,*args,**kwargs):

        print(request.version) # 获取版本
        print(request.versioning_scheme) # 获取处理版本的对象

        # rest_framework 反向生成url
        print(request.versioning_scheme.reverse(viewname='usersss',request=request))
        # django 自带反向生成url
        print(reverse(viewname='userspath',kwargs={'version':request.version}))
        return HttpResponse('用户列表')

parserdemo.py:解析器demo

from django.shortcuts import render,HttpResponse
from django.urls import reverse
from rest_framework.views import APIView
from rest_framework.request import Request

class ParserView(APIView):

    def post(self,request,*args,**kwargs):
        '''
        运行用户发送JSON格式:可以支持请求头格式
            a.content-type:application/json
            b.{'name':'alex','age':18}
        :param request:
        :param args:
        :param kwargs:
        :return:
        '''
        print(request.data)
     
     # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
     return HttpResponse('解析器')

serializersdemo.py:序列化和验证

from django.shortcuts import render
from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework import serializers
from Api import models
import json
##########################序列化##########################
# 第一种方式 Serializer
"""
class Userinfoserializers(serializers.Serializer):
    # user_type = serializers.IntegerField() #  序列化后数据对应 "user_type": 1,
    xxxxx = serializers.CharField(source='user_type') #  序列化后数据对应 "user_type": "(('普通用户', 1), ('会员用户', 2), ('管理员', 3))",
    ooooo = serializers.CharField(source='get_user_type_display')
    username = serializers.CharField()
    password = serializers.CharField()
    gp = serializers.CharField(source='group.title')  # ForeignKey使用group.title
    rls = serializers.SerializerMethodField()  # 自定义函数显示  函数名:get_字段名称

    def get_rls(self,row):
        # 获取所有角色对象
        roles_list = row.roles.all()
        result = []
        for item in roles_list:
            # 将角色对象id和title遍历出来
            result.append({'id': item.id, 'title': item.title})
        return result
"""


# 第二种方式 ModelSerializer
class Userinfoserializers(serializers.ModelSerializer):
    # 反向生成url  view_name:url别名  lookup_field: 数据库字段  lookup_url_kwarg:携带的参数/group/(?P<gid>\d+),参数可以任意命名
    group = serializers.HyperlinkedIdentityField(view_name='gp',lookup_field='group_id',lookup_url_kwarg='gid')
    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['id','username','password','group','roles']
        depth = 0  # 深度 官方建议0~10之间


class UserinfoView(APIView):

    def get(self,request,*args,**kwargs):
        response = {'status':False,'data':None}

        qdata = models.UserInfo.objects.all()
        '''
        qdata --- QuerySet对象
        instance --- QuerySet对象
        many --- 多条数据True;单条数据Flase
        context={'request': request} --- 反向生成url时需要的参数
        '''
        ser = Userinfoserializers(instance=qdata,many=True,context={'request': request})

        response['status'] = True
        response['data'] = ser.data
        return JsonResponse(response)


class Groupserializers(serializers.ModelSerializer):

    class Meta:
        model = models.UserGroup
        fields = "__all__"


class GroupView(APIView):

    def get(self,request,*args,**kwargs):
        pk = kwargs.get('gid')
        obj = models.UserGroup.objects.filter(pk=pk).first()
        ret = Groupserializers(instance=obj, many=False)
        return JsonResponse(ret.data)


##########################验证##########################

class titleValidator(object):
    def __init__(self, base):
        self.base = str(base)

    def __call__(self, value):
        print(value)
        if value != self.base:
            message = '标题必须为666 %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 UserGroupserializers(serializers.Serializer):
#     """
#     error_messages={'required':'标题不能为空'} === 验证不能为空
#     validators=[xxxValidator(666), ] === 验证函数
#     """
#     title = serializers.CharField(error_messages={'required':'标题不能为空'},validators=[titleValidator(666), ])


class UserGroupserializers(serializers.ModelSerializer):
    title = serializers.CharField()

    # 钩子函数:validate_+字段名称  value:数据

    def validate_title(self,value):
        from rest_framework import exceptions
        if value=='666':
            return value
        raise exceptions.ValidationError('title必须为666')

    class Meta:
        model = models.UserGroup
        fields = "__all__"



class UserGroupView(APIView):

    def post(self, request, *args, **kwargs):
        res = UserGroupserializers(data=request.data)
        # res.is_valid() === 返回验证结果
        if res.is_valid():
            # 验证成功后的数据
            result = res.validated_data
        else:
            # 验证失败返回的错误信息
            result = res.errors

        return JsonResponse(result)

 

posted @ 2019-04-20 14:31  我在地球凑人数的日子  阅读(135)  评论(0)    收藏  举报