1# plain.redirection
2
3**A flexible URL redirection system with admin interface and logging.**
4
5- [Overview](#overview)
6- [Basic Usage](#basic-usage)
7 - [Setting up the middleware](#setting-up-the-middleware)
8 - [Creating redirects](#creating-redirects)
9- [Advanced Features](#advanced-features)
10 - [Regex redirects](#regex-redirects)
11 - [Redirect ordering](#redirect-ordering)
12 - [Logging](#logging)
13- [Admin Interface](#admin-interface)
14- [Installation](#installation)
15
16## Overview
17
18`plain.redirection` provides a database-driven URL redirection system for Plain applications. It includes:
19
20- Database models for managing redirects
21- Middleware that intercepts 404s and checks for matching redirects
22- Support for both exact matches and regex patterns
23- Comprehensive logging of redirects and 404s
24- Built-in admin interface for managing redirects
25
26## Basic Usage
27
28### Setting up the middleware
29
30Add the [`RedirectionMiddleware`](./middleware.py#RedirectionMiddleware) to your middleware stack in `settings.py`:
31
32```python
33MIDDLEWARE = [
34 # ... other middleware ...
35 "plain.redirection.RedirectionMiddleware",
36 # This should typically be near the end of the middleware stack
37]
38```
39
40### Creating redirects
41
42You can create redirects programmatically using the [`Redirect`](./models.py#Redirect) model:
43
44```python
45from plain.redirection.models import Redirect
46
47# Simple path redirect
48Redirect.query.create(
49 from_pattern="/old-page/",
50 to_pattern="/new-page/",
51 http_status=301 # Permanent redirect
52)
53
54# Redirect with different status code
55Redirect.query.create(
56 from_pattern="/temporary-page/",
57 to_pattern="/replacement-page/",
58 http_status=302 # Temporary redirect
59)
60```
61
62## Advanced Features
63
64### Regex redirects
65
66For more complex URL patterns, you can use regex redirects:
67
68```python
69# Redirect all blog posts to a new URL structure
70Redirect.query.create(
71 from_pattern=r"^/blog/(\d{4})/(\d{2})/(.+)/$",
72 to_pattern=r"/posts/\1-\2-\3/",
73 is_regex=True,
74 http_status=301
75)
76```
77
78### Redirect ordering
79
80When multiple redirects might match a URL, you can control which one takes precedence using the `order` field:
81
82```python
83# This redirect will be checked first (lower order = higher priority)
84Redirect.query.create(
85 from_pattern="/special-case/",
86 to_pattern="/handled-specially/",
87 order=10
88)
89
90# This more general redirect will be checked later
91Redirect.query.create(
92 from_pattern=r"^/special-.*/$",
93 to_pattern="/general-handler/",
94 is_regex=True,
95 order=20
96)
97```
98
99### Logging
100
101The package automatically logs all redirects and 404s:
102
103- [`RedirectLog`](./models.py#RedirectLog) - Records successful redirects with request metadata
104- [`NotFoundLog`](./models.py#NotFoundLog) - Records 404s that didn't match any redirect
105
106Access logs programmatically:
107
108```python
109from plain.redirection.models import RedirectLog, NotFoundLog
110
111# Recent redirects
112recent_redirects = RedirectLog.query.all()[:10]
113
114# 404s from a specific IP
115not_founds = NotFoundLog.query.filter(ip_address="192.168.1.1")
116```
117
118## Admin Interface
119
120The package includes admin views for managing redirects and viewing logs. Once installed, you'll find three new sections in your admin:
121
122- **Redirects** - Create, edit, and delete redirect rules
123- **Redirect logs** - View successful redirects with full request details
124- **404 logs** - Monitor URLs that resulted in 404s
125
126The admin interface is automatically registered and will appear in the "Redirection" section of your Plain admin.
127
128## Installation
129
130Install the `plain.redirection` package from [PyPI](https://pypi.org/project/plain.redirection/):
131
132```bash
133uv add plain.redirection
134```