2016-11-20 6 views
5

APIViewから拡張されたベースAPIビューを作成しました。ここでは、応答時間、ログ要求、およびその他の一般的な情報を記録します。DRF API request.dataを使用してメソッドをディスパッチする移動要求の検証

ここで、サブクラスのビューで定義されているシリアライザを使用してリクエストの検証を追加することもできます。私は適切な場所がそれをdispatch()メソッドに入れていると思った。しかしAPI.dispatch()メソッドを呼び出す前に、request.dataは用意されていません。だから、それは動作しません。検証を単一の場所に移動する方法について、誰かが正しい方向で私を助けることができますか?

はここでクラス構造です:

class BaseView(APIView): 
    validation_serializer = None 

    def dispatch(self, request, *args, **kwargs): 
     # Some code here 
     # How to use `validation_serializer` here, to validate request data? 
     # `request.data` is not available here. 
     response = super(BaseView, self).dispatch(request, *args, **kwargs) 
     # Some code here 
     return response 

class MyView(BaseView): 
    validation_serializer = ViewValidationSerializer 

    def post(self, request, *args, **kwargs): 
     pass 

私は別のアプローチがpost()法の上使用デコレータことができると思っていました。しかし、プロジェクト全体にデコレータを置くのではなく、よりクリーンな方法があれば?

注:これは質問とよく似ています(Django - DRF - dispatch method flow)。しかし、そこに示唆されているとおり、DRFソースコードからdispatchメソッド全体をコピーするだけではありません。

答えて

1

djangoリクエストをDRFリクエストに処理して(request.dataプロパティを追加する)方法はAPIView.initialize_requestです。 APIView.dispatch() method calls itを呼び出し、適切なメソッドハンドラ(post/patch/put)を呼び出します。

あなたはそれを呼び出して、返されたオブジェクト使用して自分でやろうとすることができる:私はおそらく検証を処理する前に実行する必要がありますdispatch()の他の機能として、この反対を示唆している、しかし

class BaseView(APIView): 
    validation_serializer = None 

    def dispatch(self, request, *args, **kwargs): 
     request = self.initialize_request(request, *args, **kwargs) 
     kwargs['context'] = self.get_serializer_context() 
     serializer = self.validation_serializer(data=request.data, *args, **kwargs) 

     # use `raise_exception=True` to raise a ValidationError 
     serializer.is_valid(raise_exception=True) 

     response = super(BaseView, self).dispatch(request, *args, **kwargs) 
     return response 

を。したがって、上記のロジックをpost/patch/putメソッドに変更することができます。

self.requestは既にdispatch()で初期化されているため、直接使用することもできます。

0

私はあなたが探しているのはdrf-trackingだと思います。あなたはそれをチェックしたいかもしれません。

+0

興味深いです。しかし、それは要求の詳細を記録するためです。私が欲しいのは、検証の可能性です。 –

0

私はこの正しい方法については考えていません。検証を使用して要求を記録する最善の方法は、認証クラスにあり、要求に監査ログを追加します。

次に、APIViewを使用して、認証クラスで生成されたAuditLogに対してレンダリング時間を記録できます。


ここで、各要求は、ヘッダAuthorization: Bearer <Token>を有していると仮定すると、トークン認証を使用した例です。

settings.py

... 

REST_FRAMEWORK = { 
    'DEFAULT_AUTHENTICATION_CLASSES': (
     'common.authentication.MyTokenAuthenticationClass' 
    ), 
    ..., 
} 

共通/ authentication.py

from django.utils import timezone 
from django.utils.translation import ugettext_lazy as _ 

from ipware.ip import get_real_ip 
from rest_framework import authentication 
from rest_framework import exceptions 

from accounts.models import Token, AuditLog 


class MyTokenAuthenticationClass(authentication.BaseAuthentication): 

    def authenticate(self, request): 

     # Grab the Athorization Header from the HTTP Request 
     auth = authentication.get_authorization_header(request).split() 

     if not auth or auth[0].lower() != b'bearer': 
      return None 

     # Check that Token header is properly formatted and present, raise errors if not 
     if len(auth) == 1: 
      msg = _('Invalid token header. No credentials provided.') 
      raise exceptions.AuthenticationFailed(msg) 
     elif len(auth) > 2: 
      msg = _('Invalid token header. Credentials string should not contain spaces.') 
      raise exceptions.AuthenticationFailed(msg) 

     try: 
      token = Token.objects.get(token=auth[1]) 
      # Using the `ipware.ip` module to get the real IP (if hosted on ElasticBeanstalk or Heroku) 
      token.last_ip = get_real_ip(request) 
      token.last_login = timezone.now() 
      token.save() 

      # Add the saved token instance to the request context 
      request.token = token 

     except Token.DoesNotExist: 
      raise exceptions.AuthenticationFailed('Invalid token.') 

     # At this point, insert the Log into your AuditLog table and add to request: 
     request.audit_log = AuditLog.objects.create(
      user_id=token.user, 
      request_payload=request.body, 
      # Additional fields 
      ... 
     ) 

     # Return the Authenticated User associated with the Token 
     return (token.user, token) 

、あなたはあなたの要求に監査ログへのアクセス権を持っています。したがって、検証の前後にすべてを記録できます。

関連する問題