Python解析モジュール異常モジュール応答モジュールシーケンス化と逆シーケンス化コンポーネント

34569 ワード

解析モジュール(バックエンド指定の解析ルールに従ってフロントエンドからのデータを解析)
解析モジュールを構成する理由
1)drf                   
2)                            ,       
3)              ,              ,                  

ソースエントリ
# APIView  dispatch   
request = self.initialize_request(request, *args, **kwargs)  #    

#      
parsers=self.get_parsers(),  #    

#     (    )       (    )   parser_classes
return [parser() for parser in self.parser_classes]

次の操作を行います.
#1.グローバル構成:プロジェクトsettings.pyファイル
REST_FRAMEWORK = {
    #        
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',  # json   
        'rest_framework.parsers.FormParser',  # urlencoding   
        'rest_framework.parsers.MultiPartParser'  # form-date   
    ],
}

#2.ローカル構成:viewsを適用する.pyの具体的なビュークラス
from rest_framework.parsers import JSONParser
class Book(APIView):
    #        ,  json           
    parser_classes = [JSONParser]
    pass

例外モジュール(主にdrfが処理していない例外をカスタマイズして解決する)
例外モジュールをカスタマイズする理由
"""
1)    drf APIView        ,           
2)drf           (rest_framework.views.exception_handler),        
3)drf         ,         ,     None(             )
4)            drf       ,              ,          
"""

ソース分析
#     :APIView  dispatch   
response = self.handle_exception(exc)  #    

#          (  )
#       ,       ,    rest_framework.views exception_handler
#    :   exception_handler  ,          EXCEPTION_HANDLER     
exception_handler = self.get_exception_handler()

#        
#          exception_handler      ,        response    
response = exception_handler(exc, context)

使用方法:
#1.appアプリケーションフォルダの下にexceptionを作成する.pyファイル;カスタムシステムが例外を処理していないコードを作成します(実際のニーズに応じて作成します).
# 1)        rest_framework.views exception_handler   
# 2)       (   )response,    drf     ,None        

#          exception,      exception_handler  
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.views import Response
from rest_framework import status
def exception_handler(exc, context):
    # drf exception_handler     
    response = drf_exception_handler(exc, context)
    #
    if response is None:
        # print(exc)
        # print(context)
        print('%s - %s - %s' % (context['view'], context['request'].method, exc))
        return Response({
            'detail': '     '
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True)
    return response

#2.setting.pyファイル構成
#          setting.py
#  'EXCEPTION_HANDLER': '   .      .        '    =》                   
REST_FRAMEWORK = {
    #         
    'EXCEPTION_HANDLER': 'api.exception.exception_handler',
}

レスポンスモジュール
レスポンスクラスコンストラクタ:rest_framework.response.Response
def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
     """
        :param data:     
        :param status: http     
        :param template_name: drf       ,         (    )
        :param headers:    
        :param exception:      
        :param content_type:        (      ,      ,    json)
    """
    pass

使用シヨウ:一般的なインスタンス化された応答オブジェクト
# status                  
from rest_framework import status                  
#             ,status headers     
from rest_framework.response import Response
return Response(data={  }, status=status.HTTP_200_OK, headers={      })

シーケンス化および逆シーケンス化コンポーネント(オブジェクトとデータの相互変換):
"""
   :                  
    :                      
"""

知識点:Serializer(下位)、ModelSerializer(重点)、ListModelSerializer(サブグループ変更)
#1.例models.pyファイルテーブル:
class User(models.Model):
    SEX_CHOICES = [
        [0, ' '],
        [1, ' '],
    ]
    name = models.CharField(max_length=64)
    pwd = models.CharField(max_length=32)
    phone = models.CharField(max_length=11, null=True, default=None)
    sex = models.IntegerField(choices=SEX_CHOICES, default=0)
    icon = models.ImageField(upload_to='icon', default='icon/default.jpg')

#2.構成層:settings.py
#   rest_framework
INSTALLED_APPS = [
    # ...
    'rest_framework',
]

#      
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day70',
        'USER': 'root',
        'PASSWORD': '123'
    }
}

# media  
MEDIA_URL = '/media/'  #
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')  # media    

#      
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False

メインルーティング:プロジェクト下urls.py
from django.views.static import serve
from django.conf import settings

urlpatterns = [ # ... url(r'^api/', include('api.urls')), url(r'^media/(?P.*)', serve, {'document_root': settings.MEDIA_ROOT}), ]

サブルート
urlpatterns = [
    url(r'^users/$', views.User.as_view()),
    url(r'^users/(?P.*)/$', views.User.as_view()),
]

シーケンス化の使用
#1.appアプリケーションファイルの下にserializersを作成する.py
#2.serializers.pyファイルにシーケンス化コードを記述する
#       -     model           
#            django froms      
from rest_framework import serializers, exceptions
from django.conf import settings

from . import models

class UserSerializer(serializers.Serializer):
    name = serializers.CharField()
    phone = serializers.CharField()
    #                   ,     ,
    #
    # sex = serializers.IntegerField()
    # icon = serializers.ImageField()

    #         
    #      ,             :
    #       get_   (self,       model  )
    #                      
    gender = serializers.SerializerMethodField()
    def get_gender(self, obj):
        # choice        get_  _display()    
        return obj.get_sex_display()


    icon = serializers.SerializerMethodField()
    def get_icon(self, obj):
        # settings.MEDIA_URL:       /media/,               
        # obj.icon          ,          ,     ImageFieldFile  
        return '%s%s%s' % (r'http://127.0.0.1:8000', settings.MEDIA_URL, str(obj.icon))

ビューレイヤ
#
# UserSerializer(     , many)
# 1)        User      ,many=False(  ,      )
# 2)          User           
#       [] () {} QuerySet,  many=True    
from rest_framework.views import APIView
from rest_framework.response import Response
from . import models, serializers
class User(APIView):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        if pk:
            try:
                #                  
                user_obj = models.User.objects.get(pk=pk)
                #          
                user_ser = serializers.UserSerializer(user_obj)
                # print(user_ser, type(user_ser))
                return Response({
                    'status': 0,
                    'msg': 0,
                    'results': user_ser.data
                })
            except:
                return Response({
                    'status': 2,
                    'msg': '     ',
                })
        else:
            #       (queryset)             
            user_obj_list = models.User.objects.all()
            #          
            user_ser_data = serializers.UserSerializer(user_obj_list, many=True).data
            return Response({
                'status': 0,
                'msg': 0,
                'results': user_ser_data
            })

逆シーケンス化の使用
#1.appアプリケーションファイルの下にserializersを作成する.py
#2.serializers.pyファイルにシーケンス化コードを記述する
"""
1)            ,      
2)                  ,        ,          ,        
3)                  ,         ,        
4)  create  ,             ,       
"""
class UserDeserializer(serializers.Serializer):
    # 1)           
    # 2)           
    # 3)             
    # 4)            
    #  :             ,           ,                 (re_pwd)
    name = serializers.CharField(
        max_length=64,
        min_length=3,
        error_messages={
            'max_length': '  ',
            'min_length': '  '
        }
    )
    pwd = serializers.CharField()
    phone = serializers.CharField(required=False)
    sex = serializers.IntegerField(required=False)

    #                
    re_pwd = serializers.CharField(required=True)

    #
    # name,pwd,re_pwd     
    # phone,sex     
    #                 


    #     :validate_       (self,          )
    #     :        ,    ,    
    def validate_name(self, value):
        if 'g' in value.lower():  #        g
            raise exceptions.ValidationError('    ,    !')
        return value

    #     :validate(self,                 )
    #     :        ,    ,    
    def validate(self, attrs):
        pwd = attrs.get('pwd')
        re_pwd = attrs.pop('re_pwd')
        if pwd != re_pwd:
            raise exceptions.ValidationError({'pwd&re_pwd': '       '})
        return attrs

    #      ,       create   
    def create(self, validated_data):
        #
        return models.User.objects.create(**validated_data)

ビューレイヤ
"""
1)book_ser = serializers.UserDeserializer(data=request_data)  #       data
2)book_ser.is_valid()  #        |    
3)      book_ser.errors    ,   book_ser.save()        ,     
from rest_framework import serializers, exceptions
from django.conf import settings

from . import models

class User(APIView):
    #      
    def post(self, request, *args, **kwargs):
        #     
        request_data = request.data
        #       (            )
        if not isinstance(request_data, dict) or request_data == {}:
            return Response({
                'status': 1,
                'msg': '    ',
            })
        #       ,          ,      ,  (      )        data
        book_ser = serializers.UserDeserializer(data=request_data)

        #        is_valid()    ,                     .errors
        if book_ser.is_valid():
            #
            book_obj = book_ser.save()
            return Response({
                'status': 0,
                'msg': 'ok',
                'results': serializers.UserSerializer(book_obj).data
            })
        else:
            #     
            return Response({
                'status': 1,
                'msg': book_ser.errors,
            })