1# URLs
2
3**Route requests to views.**
4
5URLs are typically the "entrypoint" to your app. Virtually all request handling up to this point happens behind the scenes, and then you decide how to route specific URL patterns to your views.
6
7The `URLS_ROUTER` is the primary router that handles all incoming requests. It is defined in your `app/settings.py` file. This will typically point to a `Router` class in your `app.urls` module.
8
9```python
10# app/settings.py
11URLS_ROUTER = "app.urls.AppRouter"
12```
13
14The root router often has an empty namespace (`""`) and some combination of individual paths and sub-routers.
15
16```python
17# app/urls.py
18from plain.urls import Router, path, include
19from plain.admin.urls import AdminRouter
20from . import views
21
22
23class AppRouter(Router):
24 namespace = ""
25 urls = [
26 include("admin/", AdminRouter),
27 path("about/", views.AboutView, name="about"), # A named URL
28 path("", views.HomeView), # An unnamed URL
29 ]
30```
31
32## Reversing URLs
33
34In templates, you will use the `{{ url("<url name>") }}` function to look up full URLs by name.
35
36```html
37<a href="{{ url('about') }}">About</a>
38```
39
40And the same can be done in Python code with the `reverse` (or `reverse_lazy`) function.
41
42```python
43from plain.urls import reverse
44
45url = reverse("about")
46```
47
48A URL path has to include a `name` attribute if you want to reverse it. The router's `namespace` will be used as a prefix to the URL name.
49
50```python
51from plain.urls import reverse
52
53url = reverse("admin:dashboard")
54```
55
56## URL args and kwargs
57
58URL patterns can include arguments and keyword arguments.
59
60```python
61# app/urls.py
62from plain.urls import Router, path
63from . import views
64
65
66class AppRouter(Router):
67 namespace = ""
68 urls = [
69 path("user/<int:user_id>/", views.UserView, name="user"),
70 path("search/<str:query>/", views.SearchView, name="search"),
71 ]
72```
73
74These will be accessible inside the view as `self.url_args` and `self.url_kwargs`.
75
76```python
77# app/views.py
78from plain.views import View
79
80
81class SearchView(View):
82 def get(self):
83 query = self.url_kwargs["query"]
84 print(f"Searching for {query}")
85 # ...
86```
87
88To reverse a URL with args or kwargs, simply pass them in the `reverse` function.
89
90```python
91from plain.urls import reverse
92
93url = reverse("search", query="example")
94```
95
96There are a handful of built-in [converters](converters.py#DEFAULT_CONVERTERS) that can be used in URL patterns.
97
98```python
99from plain.urls import Router, path
100from . import views
101
102
103class AppRouter(Router):
104 namespace = ""
105 urls = [
106 path("user/<int:user_id>/", views.UserView, name="user"),
107 path("search/<str:query>/", views.SearchView, name="search"),
108 path("post/<slug:post_slug>/", views.PostView, name="post"),
109 path("document/<uuid:uuid>/", views.DocumentView, name="document"),
110 path("path/<path:subpath>/", views.PathView, name="path"),
111 ]
112```
113
114## Package routers
115
116Installed packages will often provide a URL router to include in your root URL router.
117
118```python
119# plain/assets/urls.py
120from plain.urls import Router, path
121from .views import AssetView
122
123
124class AssetsRouter(Router):
125 """
126 The router for serving static assets.
127
128 Include this router in your app router if you are serving assets yourself.
129 """
130
131 namespace = "assets"
132 urls = [
133 path("<path:path>", AssetView, name="asset"),
134 ]
135```
136
137Import the package's router and `include` it at any path you choose.
138
139```python
140from plain.urls import include, Router
141from plain.assets.urls import AssetsRouter
142
143
144class AppRouter(Router):
145 namespace = ""
146 urls = [
147 include("assets/", AssetsRouter),
148 # Your other URLs here...
149 ]
150```