diff --git a/sockpuppet/__init__.py b/sockpuppet/__init__.py index b08e17a..d44fd13 100644 --- a/sockpuppet/__init__.py +++ b/sockpuppet/__init__.py @@ -7,3 +7,4 @@ from sockpuppet.consumer import SockpuppetConsumer # noqa __version__ = '0.5.2' +default_app_config = 'sockpuppet.apps.SockpuppetConfig' diff --git a/sockpuppet/apps.py b/sockpuppet/apps.py index 2ad59e2..83cc3c9 100644 --- a/sockpuppet/apps.py +++ b/sockpuppet/apps.py @@ -1,6 +1,60 @@ # -*- coding: utf-8 +import inspect + from django.apps import AppConfig +from django.urls import URLPattern, URLResolver, get_resolver + +from .reflex import PROTECTED_VARIABLES, Reflex class SockpuppetConfig(AppConfig): name = 'sockpuppet' + + def ready(self): + process_resolver(get_resolver()) + + +def get_context_data(self, **context): + context = self._patched_get_context_data(**context) + + try: + reflex = self.request.reflex + except AttributeError: + pass + else: + instance_variables = [ + name for (name, member) in inspect.getmembers(reflex) + if not name.startswith('__') and name not in PROTECTED_VARIABLES + ] + reflex_context = {key: getattr(reflex, key) for key in instance_variables} + reflex_context['stimulus_reflex'] = True + + reflex.get_context_data(**reflex_context) + context.update(reflex_context) + + return context + + +def process_callback(callback): + try: + view_class = callback.view_class + view_class._patched_get_context_data = view_class.get_context_data + view_class.get_context_data = get_context_data + except AttributeError: + pass + + return callback + + +def process_resolver(resolver: URLResolver) -> None: + if resolver.callback: + resolver.callback = process_callback(resolver.callback) + + for pattern in resolver.url_patterns: + if isinstance(pattern, URLPattern) and pattern.callback: + pattern.callback = process_callback(pattern.callback) + elif isinstance(pattern, URLResolver): + process_resolver(pattern) + + if resolver._populated: + resolver._populate() diff --git a/sockpuppet/reflex.py b/sockpuppet/reflex.py index ae4bc73..38de7a1 100644 --- a/sockpuppet/reflex.py +++ b/sockpuppet/reflex.py @@ -2,6 +2,8 @@ from urllib.parse import urlparse from django.test import RequestFactory +from django.utils.functional import cached_property + PROTECTED_VARIABLES = [ 'consumer', @@ -36,7 +38,7 @@ def get_context_data(self, *args, **kwargs): view.request = self.request try: view.kwargs = resolved.kwargs - context = view.get_context_data() + context = view._patched_get_context_data() except AttributeError: view.get(self.request) context = view.get_context_data() @@ -52,13 +54,14 @@ def get_channel_id(self): ''' return self.session.session_key - @property + @cached_property def request(self): factory = RequestFactory() request = factory.get(self.url) request.session = self.consumer.scope['session'] request.user = self.consumer.scope['user'] request.POST = self.params + request.reflex = self return request def reload(self):