1from plain.http import ResponseRedirect
2from plain.urls import reverse
3
4from .base import View
5
6
7class RedirectView(View):
8 """Provide a redirect on any GET request."""
9
10 status_code = 302
11 url: str | None = None
12 url_name: str | None = None
13 preserve_query_params = False
14
15 def __init__(
16 self,
17 url: str | None = None,
18 status_code: int | None = None,
19 url_name: str | None = None,
20 preserve_query_params: bool | None = None,
21 ) -> None:
22 # Allow attributes to be set in RedirectView.as_view(url="...", status_code=301, etc.)
23 self.url = url or self.url
24 self.status_code = status_code if status_code is not None else self.status_code
25 self.url_name = url_name or self.url_name
26 self.preserve_query_params = (
27 preserve_query_params
28 if preserve_query_params is not None
29 else self.preserve_query_params
30 )
31
32 def get_redirect_url(self) -> str:
33 """
34 Return the URL redirect to. Keyword arguments from the URL pattern
35 match generating the redirect request are provided as kwargs to this
36 method.
37 """
38 if self.url:
39 url = self.url % self.url_kwargs
40 elif self.url_name:
41 url = reverse(self.url_name, *self.url_args, **self.url_kwargs)
42 else:
43 raise ValueError("RedirectView requires either url or url_name to be set")
44
45 args = self.request.meta.get("QUERY_STRING", "")
46 if args and self.preserve_query_params:
47 url = f"{url}?{args}"
48 return url
49
50 def get(self) -> ResponseRedirect:
51 url = self.get_redirect_url()
52 return ResponseRedirect(url, status_code=self.status_code)
53
54 def head(self) -> ResponseRedirect:
55 return self.get()
56
57 def post(self) -> ResponseRedirect:
58 return self.get()
59
60 def options(self) -> ResponseRedirect:
61 return self.get()
62
63 def delete(self) -> ResponseRedirect:
64 return self.get()
65
66 def put(self) -> ResponseRedirect:
67 return self.get()
68
69 def patch(self) -> ResponseRedirect:
70 return self.get()