Skip to content

Instantly share code, notes, and snippets.

@kevin-brown
Last active November 28, 2019 09:27
Show Gist options
  • Save kevin-brown/3e6fd950f10dacde0357 to your computer and use it in GitHub Desktop.
Save kevin-brown/3e6fd950f10dacde0357 to your computer and use it in GitHub Desktop.
DRF and Django compatible initialization mixin
class CompatibleDispatchInitialization(object):
"""
Allow data to be initialized before a view is fully dispatched in a way
that is consistent across both standard Django views and Django REST
Framework views.
While initializing data would typically be done within `dispatch`, the
request is not fully initialized at that point during DRF views which
causes issues with authentication. For this reason, it is recommended to
do data initialization within the `initial` method for DRF views. The
`initial` property exists on any Django views that use forms, such as the
generic editing views, so it can not be directly overridden. Because of
this, the method is swapped out during `dispatch` to ensure there are no
unexpected side effects.
The method that should be overridden in superclasses to initialize data
consistently is the `_initialize_data` method. This method will be
passed the request, which should contain an authenticated user if needed,`
as well as the args and kwargs passed into the view. The method signature
matches the `dispatch` method.
**Notes:**
- Views by default will not have the CSRF check done to ensure
compatibility with Django REST Framework. For standard Django views, the
CSRF middleware will be triggered manually. For Django REST Framework
views, DRF is expected to handle CSRF validation.
"""
@csrf_exempt
def dispatch(self, request, *args, **kwargs):
"""
The incoming request is determined to be for a DRF view if the view
implements the `initialize_request` method.
CSRF validation is done within this method for standard Django views
using the technique used by Django REST Framework.
https://github.com/tomchristie/django-rest-framework/blob/5333a9312613cffa573b4b38acfaa8d402286174/rest_framework/authentication.py
"""
if not hasattr(self, "initialize_request"):
from django.middleware.csrf import CsrfViewMiddleware
self._initialize_data(request, *args, **kwargs)
response = CsrfViewMiddleware().process_view(request, None, (), {})
if response:
return response
else:
self.initial = self._initial
return super(CompatibleDispatchInitialization, self) \
.dispatch(request, *args, **kwargs)
def _initial(self, request, *args, **kwargs):
super(CompatibleDispatchInitialization, self) \
.initial(request, *args, **kwargs)
self._initialize_data(request, *args, **kwargs)
def _initialize_data(self, request, *args, **kwargs):
"""
Stub method that should be overriden, keep this to ensure that `super`
calls still work.
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment