2016-11-20 14 views
5

का उपयोग करके प्रेषण विधि को स्थानांतरित करने के लिए सत्यापन अनुरोध सत्यापन मैंने एक बेस एपीआई व्यू बनाया है, जो APIView से फैला है, जहां मैं प्रतिक्रिया समय, लॉग अनुरोध, और अन्य सामान्य सामान लॉग करता हूं।DRF APIView 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। लेकिन सुझाव के मुताबिक, मैं डीआरएफ स्रोत कोड से पूरी dispatch विधि की प्रतिलिपि बनाना नहीं चाहता हूं।

उत्तर

1

विधि जो डीजेए अनुरोध को डीआरएफ अनुरोध में संसाधित करती है (और request.data संपत्ति जोड़ती है) APIView.initialize_request है। APIView.dispatch() method calls it और उसके बाद उपयुक्त विधि हैंडलर (पोस्ट/पैच/) को कॉल करने के लिए आगे बढ़ता है।

आप इसे बुला और लौट आए वस्तु का उपयोग करके अपने आप को ऐसा करने की कोशिश कर सकते हैं: मैं 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 

हालांकि; इस प्रकार, आप उपर्युक्त तर्क को प्रासंगिक पोस्ट/पैच/ विधियों के बजाय स्थानांतरित कर सकते हैं।

इन तरीकों में आप सीधे self.request का उपयोग भी कर सकते हैं क्योंकि यह पहले से ही dispatch() द्वारा प्रारंभ किया गया था।

0

मुझे लगता है कि drf-tracking जो आप ढूंढ रहे हैं वह करता है। इसे आज़माने की आपकी इच्छा हो सकती है।

+0

दिलचस्प लग रहा है। लेकिन यह अनुरोध विवरण लॉगिंग के लिए है। मैं चाहता हूं कि सत्यापन की संभावना है। –

0

मुझे नहीं लगता कि आप इस बारे में सही तरीके से जा रहे हैं। अनुरोध को लॉग करने का सबसे अच्छा तरीका, सत्यापन के साथ आपकी प्रमाणीकरण कक्षा में है और अनुरोध पर ऑडिट लॉग जोड़ें।

फिर आप प्रमाणीकरण कक्षा में उत्पन्न AuditLog के विरुद्ध, रेंडर समय लॉग करने के लिए अपने APIView का उपयोग कर सकते हैं।


यहाँ टोकन प्रमाणीकरण का उपयोग कर एक उदाहरण है, यह मानते हुए प्रत्येक अनुरोध एक हैडर 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) 

अब, आप अपने अनुरोध में AuditLog की पहुंच है।तो आप प्रमाणीकरण से पहले और बाद में सबकुछ लॉग कर सकते हैं।

संबंधित मुद्दे