import pghistory from django.contrib.auth.models import AnonymousUser from django.core.handlers.wsgi import WSGIRequest from django.utils.deprecation import MiddlewareMixin from django.contrib.contenttypes.models import ContentType from django.views.generic.detail import DetailView from core.analytics import PageView class RequestContextProvider(pghistory.context): """Custom context provider for pghistory that extracts information from the request.""" def __call__(self, request: WSGIRequest) -> dict: return { 'user': str(request.user) if request.user and not isinstance(request.user, AnonymousUser) else None, 'ip': request.META.get('REMOTE_ADDR'), 'user_agent': request.META.get('HTTP_USER_AGENT'), 'session_key': request.session.session_key if hasattr(request, 'session') else None } # Initialize the context provider request_context = RequestContextProvider() class PgHistoryContextMiddleware: """ Middleware that ensures request object is available to pghistory context. """ def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response class PageViewMiddleware(MiddlewareMixin): def process_view(self, request, view_func, view_args, view_kwargs): # Only track GET requests if request.method != 'GET': return None # Get view class if it exists view_class = getattr(view_func, 'view_class', None) if not view_class or not issubclass(view_class, DetailView): return None # Get the object if it's a detail view try: view_instance = view_class() view_instance.request = request view_instance.args = view_args view_instance.kwargs = view_kwargs obj = view_instance.get_object() except (AttributeError, Exception): return None # Record the page view try: PageView.objects.create( content_type=ContentType.objects.get_for_model(obj.__class__), object_id=obj.pk, ip_address=request.META.get('REMOTE_ADDR', ''), user_agent=request.META.get('HTTP_USER_AGENT', '')[:512] ) except Exception: # Fail silently to not interrupt the request pass return None