comparison piecrust/serving/util.py @ 723:606f6d57b5df

routing: Cleanup URL routing and improve page matching. * Add new types of route parameters for integers (int4, int2, int). * Remove hard-coded hacks around converting year/month/day values. * Make the blog post routes use the new typed parameters. * Fix problems with matching routes with integer parameters when they can get confused with a sub-page number.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 29 May 2016 20:19:28 -0700
parents ab5c6a8ae90a
children dfd9f5ee4622
comparison
equal deleted inserted replaced
722:f0a3af3fbea2 723:606f6d57b5df
22 app.config.set('server/is_serving', True) 22 app.config.set('server/is_serving', True)
23 return app 23 return app
24 24
25 25
26 class RequestedPage(object): 26 class RequestedPage(object):
27 def __init__(self, qualified_page): 27 def __init__(self):
28 self.qualified_page = qualified_page 28 self.qualified_page = None
29 self.req_path = None 29 self.req_path = None
30 self.page_num = 1 30 self.page_num = 1
31 self.not_found_errors = [] 31 self.not_found_errors = []
32 32
33 33
34 def find_routes(routes, uri): 34 def find_routes(routes, uri, is_sub_page=False):
35 """ Returns routes matching the given URL, but puts generator routes 35 """ Returns routes matching the given URL, but puts generator routes
36 at the end. 36 at the end.
37 """ 37 """
38 res = [] 38 res = []
39 gen_res = [] 39 gen_res = []
40 for route in routes: 40 for route in routes:
41 metadata = route.matchUri(uri) 41 metadata = route.matchUri(uri)
42 if metadata is not None: 42 if metadata is not None:
43 if route.is_source_route: 43 if route.is_source_route:
44 res.append((route, metadata)) 44 res.append((route, metadata, is_sub_page))
45 else: 45 else:
46 gen_res.append((route, metadata)) 46 gen_res.append((route, metadata, is_sub_page))
47 return res + gen_res 47 return res + gen_res
48 48
49 49
50 def get_requested_page(app, req_path): 50 def get_requested_page(app, req_path):
51 # Try to find what matches the requested URL. 51 # Try to find what matches the requested URL.
52 req_path, page_num = split_sub_uri(app, req_path) 52 routes = find_routes(app.routes, req_path)
53 53
54 routes = find_routes(app.routes, req_path) 54 # It could also be a sub-page (i.e. the URL ends with a page number), so
55 # we try to also match the base URL (without the number).
56 req_path_no_num, page_num = split_sub_uri(app, req_path)
57 if page_num > 1:
58 routes += find_routes(app.routes, req_path_no_num, True)
59
55 if len(routes) == 0: 60 if len(routes) == 0:
56 raise RouteNotFoundError("Can't find route for: %s" % req_path) 61 raise RouteNotFoundError("Can't find route for: %s" % req_path)
57 62
58 qp = None 63 req_page = RequestedPage()
59 not_found_errors = [] 64 for route, route_metadata, is_sub_page in routes:
60 for route, route_metadata in routes:
61 try: 65 try:
66 cur_req_path = req_path
67 if is_sub_page:
68 cur_req_path = req_path_no_num
69
62 qp = _get_requested_page_for_route( 70 qp = _get_requested_page_for_route(
63 app, route, route_metadata, req_path) 71 app, route, route_metadata, cur_req_path)
64 if qp is not None: 72 if qp is not None:
73 req_page.qualified_page = qp
74 req_page.req_path = cur_req_path
75 if is_sub_page:
76 req_page.page_num = page_num
65 break 77 break
66 except PageNotFoundError as nfe: 78 except PageNotFoundError as nfe:
67 not_found_errors.append(nfe) 79 req_page.not_found_errors.append(nfe)
68
69 req_page = RequestedPage(qp)
70 req_page.req_path = req_path
71 req_page.page_num = page_num
72 req_page.not_found_errors = not_found_errors
73 return req_page 80 return req_page
74 81
75 82
76 def _get_requested_page_for_route(app, route, route_metadata, req_path): 83 def _get_requested_page_for_route(app, route, route_metadata, req_path):
77 if not route.is_generator_route: 84 if not route.is_generator_route: