0
# URL Generation and Registration
1
2
Advanced URL generation system for handling dynamic routes, custom URL patterns, and endpoint discovery. Frozen-Flask uses URL generators to discover all URLs that should be converted to static files.
3
4
## Capabilities
5
6
### Generator Registration
7
8
Methods for registering custom URL generator functions to handle dynamic routes and custom URL patterns.
9
10
```python { .api }
11
def register_generator(self, function):
12
"""
13
Register a function as a URL generator.
14
15
The function should return an iterable of:
16
- URL strings: '/some/path/'
17
- (endpoint, values) tuples: ('product', {'id': 1})
18
- (endpoint, values, last_modified) tuples for incremental builds
19
- Values dictionaries (endpoint defaults to function name)
20
21
Parameters:
22
- function: Generator function returning URL patterns
23
24
Returns:
25
function: The function (allows use as decorator)
26
"""
27
```
28
29
### Built-in URL Generators
30
31
Default URL generators for common Flask patterns.
32
33
```python { .api }
34
def static_files_urls(self):
35
"""
36
URL generator for static files for app and all blueprints.
37
38
Yields:
39
tuple: (endpoint, {'filename': relative_path}) for each static file
40
"""
41
42
def no_argument_rules_urls(self):
43
"""
44
URL generator for URL rules that take no arguments.
45
46
Yields:
47
tuple: (endpoint, {}) for each no-argument route
48
"""
49
```
50
51
### Internal URL Processing
52
53
Internal methods for URL discovery and processing.
54
55
```python { .api }
56
def _generate_all_urls(self):
57
"""
58
Run all generators and yield (url, endpoint, last_modified) tuples.
59
60
Internal method that processes all registered generators.
61
"""
62
63
def _static_rules_endpoints(self):
64
"""
65
Yield the 'static' URL rules for the app and all blueprints.
66
67
Internal method for identifying static file endpoints.
68
"""
69
```
70
71
## URL Generator Patterns
72
73
### String URLs
74
75
Simplest pattern - return URL strings directly:
76
77
```python
78
@freezer.register_generator
79
def product_urls():
80
yield '/product/1/'
81
yield '/product/2/'
82
yield '/about/'
83
```
84
85
### Endpoint and Values
86
87
Use Flask's `url_for` pattern with endpoint names and parameters:
88
89
```python
90
@freezer.register_generator
91
def product_urls():
92
# (endpoint, values) tuples
93
yield 'product', {'id': 1}
94
yield 'product', {'id': 2}
95
yield 'page', {'name': 'about'}
96
```
97
98
### Values Dictionary
99
100
When the endpoint matches the generator function name:
101
102
```python
103
@freezer.register_generator
104
def product(): # Function name becomes endpoint
105
# Just values dictionary
106
yield {'id': 1}
107
yield {'id': 2}
108
yield {'id': 3}
109
```
110
111
### Incremental Builds
112
113
Include last modified timestamps for smart rebuilding:
114
115
```python
116
from datetime import datetime
117
118
@freezer.register_generator
119
def blog_posts():
120
posts = get_blog_posts() # Your data source
121
for post in posts:
122
yield 'blog_post', {'slug': post.slug}, post.updated_at
123
```
124
125
## Usage Examples
126
127
### Dynamic Product Pages
128
129
```python
130
from flask import Flask
131
from flask_frozen import Freezer
132
133
app = Flask(__name__)
134
freezer = Freezer(app)
135
136
@app.route('/product/<int:product_id>/')
137
def product(product_id):
138
return f'Product {product_id}'
139
140
@freezer.register_generator
141
def product_urls():
142
# Generate URLs for products 1-10
143
for i in range(1, 11):
144
yield 'product', {'product_id': i}
145
146
freezer.freeze()
147
```
148
149
### Blog with Categories
150
151
```python
152
@app.route('/blog/<category>/<slug>/')
153
def blog_post(category, slug):
154
return f'Blog post: {category}/{slug}'
155
156
@freezer.register_generator
157
def blog_urls():
158
posts = [
159
('tech', 'python-tips'),
160
('tech', 'flask-guide'),
161
('news', 'company-update'),
162
]
163
for category, slug in posts:
164
yield 'blog_post', {'category': category, 'slug': slug}
165
```
166
167
### Database-Driven URLs
168
169
```python
170
@freezer.register_generator
171
def user_profile_urls():
172
# Get data from database
173
users = User.query.filter_by(active=True).all()
174
for user in users:
175
yield 'user_profile', {'username': user.username}
176
```
177
178
### Mixed URL Patterns
179
180
```python
181
@freezer.register_generator
182
def mixed_urls():
183
# Direct URL strings
184
yield '/special-page/'
185
yield '/robots.txt'
186
187
# Endpoint and values
188
yield 'category', {'name': 'electronics'}
189
yield 'category', {'name': 'books'}
190
191
# Values only (endpoint = function name = 'mixed_urls')
192
# This won't work unless you have a route named 'mixed_urls'
193
```
194
195
### Conditional Generation
196
197
```python
198
@freezer.register_generator
199
def conditional_urls():
200
# Only generate certain URLs in production
201
if app.config.get('ENV') == 'production':
202
yield '/admin-report/'
203
yield '/analytics/'
204
205
# Always generate these
206
yield '/sitemap.xml'
207
yield '/feed.xml'
208
```
209
210
## Static File Handling
211
212
Static files are handled automatically when `with_static_files=True` (default):
213
214
```python
215
# This automatically includes all static files
216
freezer = Freezer(app, with_static_files=True)
217
218
# To disable automatic static file inclusion
219
freezer = Freezer(app, with_static_files=False)
220
221
# To manually include static files
222
@freezer.register_generator
223
def my_static_files():
224
# Custom static file logic
225
yield 'static', {'filename': 'css/style.css'}
226
yield 'static', {'filename': 'js/app.js'}
227
```
228
229
## No-Argument Routes
230
231
Routes without parameters are handled automatically when `with_no_argument_rules=True` (default):
232
233
```python
234
@app.route('/')
235
def index():
236
return 'Home'
237
238
@app.route('/about/')
239
def about():
240
return 'About'
241
242
# These are automatically included - no generator needed
243
freezer = Freezer(app, with_no_argument_rules=True)
244
```