Plain is headed towards 1.0! Subscribe for development updates →

  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```