Files
thrillwiki_django_no_react/core/views/views.py
2025-08-15 12:24:20 -04:00

62 lines
2.5 KiB
Python

from typing import Any, Dict, Optional, Type, cast
from django.shortcuts import redirect
from django.urls import reverse
from django.views.generic import DetailView
from django.views import View
from django.http import HttpRequest, HttpResponse
from django.db.models import Model
class SlugRedirectMixin(View):
"""
Mixin that handles redirects for old slugs.
Requires the model to inherit from SluggedModel and view to inherit from DetailView.
"""
model: Optional[Type[Model]] = None
slug_url_kwarg: str = 'slug'
object: Optional[Model] = None
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
# Only apply slug redirect logic to DetailViews
if not isinstance(self, DetailView):
return super().dispatch(request, *args, **kwargs)
# Get the object using current or historical slug
try:
self.object = self.get_object() # type: ignore
# Check if we used an old slug
current_slug = kwargs.get(self.slug_url_kwarg)
if current_slug and current_slug != getattr(self.object, 'slug', None):
# Get the URL pattern name from the view
url_pattern = self.get_redirect_url_pattern()
# Build kwargs for reverse()
reverse_kwargs = self.get_redirect_url_kwargs()
# Redirect to the current slug URL
return redirect(
reverse(url_pattern, kwargs=reverse_kwargs),
permanent=True
)
return super().dispatch(request, *args, **kwargs)
except (AttributeError, Exception) as e: # type: ignore
if self.model and hasattr(self.model, 'DoesNotExist'):
if isinstance(e, self.model.DoesNotExist): # type: ignore
return super().dispatch(request, *args, **kwargs)
return super().dispatch(request, *args, **kwargs)
def get_redirect_url_pattern(self) -> str:
"""
Get the URL pattern name for redirects.
Should be overridden by subclasses.
"""
raise NotImplementedError(
"Subclasses must implement get_redirect_url_pattern()"
)
def get_redirect_url_kwargs(self) -> Dict[str, Any]:
"""
Get the kwargs for reverse() when redirecting.
Should be overridden by subclasses if they need custom kwargs.
"""
if not self.object:
return {}
return {self.slug_url_kwarg: getattr(self.object, 'slug', '')}