Plain is headed towards 1.0! Subscribe for development updates →

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