Last active
November 28, 2019 09:27
-
-
Save kevin-brown/3e6fd950f10dacde0357 to your computer and use it in GitHub Desktop.
DRF and Django compatible initialization mixin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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