urls.js
? ๐คท
Instead of defining routes in your code...
Instead of defining routes in your code...
...routes are defined by your code.
Instead of defining routes in your code...
...routes are defined by your code structure.
/blog
/
pages/index.jsx โ /
pages/blog/index.jsx โ /blog
pages/index.jsx โ /
pages/blog/index.jsx โ /blog
How is this possible?
export
s// pages/index.jsx export function HomePage() { return <h1>Hello, world!</h1>; }
// pages/index.jsx export function HomePage() { return <h1>Hello, world!</h1>; }
export
s// pages/index.jsx export default function HomePage() { return <h1>Hello, world!</h1>; }
// pages/index.jsx export default function HomePage() { return <h1>Hello, world!</h1>; }
pages/
โโโ blog/
โ โโโ index.jsx โ /blog
โ โโโ first-post.jsx โ /blog/first-post
โโโ settings/
โ โโโ account/
โ โโโ password.jsx โ /settings/account/password
โโโ index.jsx โ /
pages/
โโโ blog/
โ โโโ index.jsx โ /blog
โ โโโ [slug].jsx โ /blog/:slug
โโโ profile/
โ โโโ [username]/
โ โโโ index.jsx โ /profile/:username
โ โโโ likes.jsx โ /profile/:username/likes
โโโ settings/
โ โโโ account/
โ โโโ password.jsx โ /settings/account/password
โโโ unknown/
โ โโโ [...all].jsx โ /unknown/*
โโโ index.jsx โ /
root.jsx โ /
routes/
โโโ blog/
โ โโโ index.jsx โ /blog
โ โโโ $slug.jsx โ /blog/:slug
โโโ profile/
โ โโโ $username/
โ โ โโโ likes.jsx โ /profile/:username/likes
โ โโโ $username.jsx โ /profile/:username
โโโ settings/
โ โโโ account/
โ โโโ password.jsx โ /settings/account/password
โโโ unknown/
โโโ $.jsx โ /unknown/*
pages/
โโโ blog/
โ โโโ index.vue โ /blog
โ โโโ _slug.vue โ /blog/:slug
โโโ profile/
โ โโโ _username/
โ โโโ index.vue โ /profile/:username
โ โโโ likes.vue โ /profile/:username/likes
โโโ settings/
โ โโโ account/
โ โโโ password.vue โ /settings/account/password
โโโ unknown/
โ โโโ _.vue โ /unknown/*
โโโ index.vue โ /
routes/ โ /
โโโ blog/ โ /blog
โ โโโ +page.svelte
โ โโโ [slug]/ โ /blog/:slug
โ โโโ +page.svelte
โโโ profile/
โ โโโ [username]/ โ /profile/:username
โ โโโ +page.svelte
โ โโโ likes/ โ /profile/:username/likes
โ โโโ +page.svelte
โโโ settings/
โ โโโ account/
โ โโโ password/ โ /settings/account/password
โ โโโ +page.svelte
โโโ unknown/
โ โโโ [...rest]/ โ /unknown/*
โ โโโ +error.svelte
โ โโโ +page.svelte
โโโ +page.svelte
pages/
โโโ blog/
โ โโโ {MarkdownRemark.parent__(File)__name}.js โ /blog/:filename
โโโ products/
โ โโโ {Product.category}/
โ โโโ {Product.fields__sku}.js โ /products/:category/:sku
โโโ profile/
โ โโโ [id]/
โ โ โโโ group/
โ โ โโโ [groupId].js โ /profile/:id/group/:groupId
โ โโโ [id].js โ /profile/:id
โโโ unknown/
โโโ [...rest].js โ /unknown/*
code structure โ๏ธ url structure
import BlogPost from 'pages/blog/[slug]';
pages/
โโโ about.jsx
โโโ index.jsx
โโโ posts/
โ โโโ [slug].jsx
โ โโโ index.jsx
โโโ projects/
โโโ [id].jsx
โโโ index.jsx
pages/
โโโ about.jsx
โโโ index.jsx
โโโ posts/
โ โโโ [slug].jsx
โ โโโ index.jsx
โโโ projects/
โโโ [id].jsx
โโโ index.jsx
myapp/views/
โโโ about.py
โโโ index.py
โโโ posts/
โ โโโ [slug].py
โ โโโ index.py
โโโ projects/
โโโ [id].py
โโโ index.py
pages/
โโโ about.jsx
โโโ index.jsx
โโโ posts/
โ โโโ [slug].jsx
โ โโโ index.jsx
โโโ projects/
โโโ [id].jsx
โโโ index.jsx
myapp/views/
โโโ about.py
โโโ __init__.py
โโโ posts/
โ โโโ [slug].py
โ โโโ __init__.py
โโโ projects/
โโโ [id].py
โโโ __init__.py
pages/
โโโ about.jsx
โโโ index.jsx
โโโ posts/
โ โโโ [slug].jsx
โ โโโ index.jsx
โโโ projects/
โโโ [id].jsx
โโโ index.jsx
myapp/views/
โโโ about.py
โโโ __init__.py
โโโ posts/
โ โโโ <slug:slug>.py
โ โโโ __init__.py
โโโ projects/
โโโ <int:id>.py
โโโ __init__.py
pages/
โโโ about.jsx
โโโ index.jsx
โโโ posts/
โ โโโ [slug].jsx
โ โโโ index.jsx
โโโ projects/
โโโ [id].jsx
โโโ index.jsx
myapp/views/
โโโ about.py
โโโ __init__.py
โโโ posts/
โ โโโ __slug__slug__.py
โ โโโ __init__.py
โโโ projects/
โโโ __int__id__.py
โโโ __init__.py
pages/
โโโ about.jsx
โโโ index.jsx
โโโ posts/
โ โโโ [slug].jsx
โ โโโ index.jsx
โโโ projects/
โโโ [id].jsx
โโโ index.jsx
myapp/views/
โโโ about.py
โโโ __init__.py
โโโ posts/
โ โโโ slug.py
โ โโโ __init__.py
โโโ projects/
โโโ id.py
โโโ __init__.py
export default function HomePage() {
return <h1>Hello, world!</h1>;
}
export default function HomePage() {
return <h1>Hello, world!</h1>;
}
def default(request):
return HttpResponse("Hello, world!")
export default function HomePage() {
return <h1>Hello, world!</h1>;
}
def view(request):
return HttpResponse("Hello, world!")
export default function HomePage() {
return <h1>Hello, world!</h1>;
}
def dispatch(request):
return HttpResponse("Hello, world!")
urls.py
urls.py
urlpatterns = [ fs_paths("myapp.views"), # or fs_paths("myapp/views") ? # or *fs_paths("myapp/views") ? ]
urlpatterns = [ fs_paths("myapp.views"), # or fs_paths("myapp/views") ? # or *fs_paths("myapp/views") ? ]
fs_paths
fs_paths
def fs_paths(module_path):
...
fs_paths
def fs_paths(module_path): # 1. Get the module object from module_path (dynamic import)
fs_paths
def fs_paths(module_path): # 1. Get the module object from module_path (dynamic import) # 2. Use getattr(module, "dispatch") to get the view function
fs_paths
def fs_paths(module_path): # 1. Get the module object from module_path (dynamic import) # 2. Use getattr(module, "dispatch") to get the view function # 3. Construct path(route, view)
fs_paths
def fs_paths(module_path): # 1. Get the module object from module_path (dynamic import) # 2. Use getattr(module, "dispatch") to get the view function # 3. Construct path(route, view) # 4. Repeat for all submodules
def fs_paths(module_path): # 1. Get the module object from module_path (dynamic import) # 2. Use getattr(module, "dispatch") to get the view function # 3. Construct path(route, view) # 4. Repeat for all submodules
fs_paths
from importlib import import_module def fs_paths(module_path): module = import_module(module_path) # 2. Use getattr(module, "dispatch") to get the view function # 3. Construct path(route, view) # 4. Repeat for all submodules
from importlib import import_module def fs_paths(module_path): module = import_module(module_path) # 2. Use getattr(module, "dispatch") to get the view function # 3. Construct path(route, view) # 4. Repeat for all submodules
fs_paths
from importlib import import_module def fs_paths(module_path): module = import_module(module_path) view = getattr(module, "dispatch") # 3. Construct path(route, view) # 4. Repeat for all submodules
from importlib import import_module def fs_paths(module_path): module = import_module(module_path) view = getattr(module, "dispatch") # 3. Construct path(route, view) # 4. Repeat for all submodules
fs_paths
from importlib import import_module from django.urls import path def fs_paths(module_path): module = import_module(module_path) view = getattr(module, "dispatch") return path("", view, name="index") # 4. Repeat for all submodules
from importlib import import_module from django.urls import path def fs_paths(module_path): module = import_module(module_path) view = getattr(module, "dispatch") return path("", view, name="index") # 4. Repeat for all submodules
fs_paths
from importlib import import_module from django.urls import path def fs_paths(module_path): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) return path("", include((result, module_path)))
from importlib import import_module from django.urls import path def fs_paths(module_path): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) return path("", include((result, module_path)))
from importlib import import_module from django.urls import path def fs_paths(module_path): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) return path("", include((result, module_path)))
fs_paths
from importlib import import_module from django.urls import path def fs_paths(module_path, namespace=None): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) if not namespace: namespace = module_path return path("", include((result, namespace)))
fs_paths
from pkgutil import walk_packages from importlib import import_module from django.urls import path def fs_paths(module_path, namespace=None): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) if not namespace: namespace = module_path prefix = f"{module_path}.") for pkg in walk_packages(module.__path__, prefix=prefix): finder, name, _ = pkg # pkgutil.ModuleInfo module = finder.find_module(name).load_module(name) view = getattr(module, "dispatch", None) route_name = name[len(prefix):] route = route_name.replace('.', '/') if callable(view): result.append(path(route, view, name=route_name)) result.sort(key=lambda x: str(x.pattern), reverse=True) return path("", include((result, namespace)))
from pkgutil import walk_packages from importlib import import_module from django.urls import path def fs_paths(module_path, namespace=None): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) if not namespace: namespace = module_path prefix = f"{module_path}.") for pkg in walk_packages(module.__path__, prefix=prefix): finder, name, _ = pkg # pkgutil.ModuleInfo module = finder.find_module(name).load_module(name) view = getattr(module, "dispatch", None) route_name = name[len(prefix):] route = route_name.replace('.', '/') if callable(view): result.append(path(route, view, name=route_name)) result.sort(key=lambda x: str(x.pattern), reverse=True) return path("", include((result, namespace)))
from pkgutil import walk_packages from importlib import import_module from django.urls import path def fs_paths(module_path, namespace=None): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) if not namespace: namespace = module_path prefix = f"{module_path}.") for pkg in walk_packages(module.__path__, prefix=prefix): finder, name, _ = pkg # pkgutil.ModuleInfo module = finder.find_module(name).load_module(name) view = getattr(module, "dispatch", None) route_name = name[len(prefix):] route = route_name.replace('.', '/') if callable(view): result.append(path(route, view, name=route_name)) result.sort(key=lambda x: str(x.pattern), reverse=True) return path("", include((result, namespace)))
from pkgutil import walk_packages from importlib import import_module from django.urls import path def fs_paths(module_path, namespace=None): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) if not namespace: namespace = module_path prefix = f"{module_path}.") for pkg in walk_packages(module.__path__, prefix=prefix): finder, name, _ = pkg # pkgutil.ModuleInfo module = finder.find_module(name).load_module(name) view = getattr(module, "dispatch", None) route_name = name[len(prefix):] route = route_name.replace('.', '/') if callable(view): result.append(path(route, view, name=route_name)) result.sort(key=lambda x: str(x.pattern), reverse=True) return path("", include((result, namespace)))
from pkgutil import walk_packages from importlib import import_module from django.urls import path def fs_paths(module_path, namespace=None): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) if not namespace: namespace = module_path prefix = f"{module_path}.") for pkg in walk_packages(module.__path__, prefix=prefix): finder, name, _ = pkg # pkgutil.ModuleInfo module = finder.find_module(name).load_module(name) view = getattr(module, "dispatch", None) route_name = name[len(prefix):] route = route_name.replace('.', '/') if callable(view): result.append(path(route, view, name=route_name)) result.sort(key=lambda x: str(x.pattern), reverse=True) return path("", include((result, namespace)))
from pkgutil import walk_packages from importlib import import_module from django.urls import path def fs_paths(module_path, namespace=None): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) if not namespace: namespace = module_path prefix = f"{module_path}.") for pkg in walk_packages(module.__path__, prefix=prefix): finder, name, _ = pkg # pkgutil.ModuleInfo module = finder.find_module(name).load_module(name) view = getattr(module, "dispatch", None) route_name = name[len(prefix):] route = route_name.replace('.', '/') if callable(view): result.append(path(route, view, name=route_name)) result.sort(key=lambda x: str(x.pattern), reverse=True) return path("", include((result, namespace)))
from pkgutil import walk_packages from importlib import import_module from django.urls import path def fs_paths(module_path, namespace=None): result = [] module = import_module(module_path) view = getattr(module, "dispatch", None) if callable(view): result.append(path("", view, name="index")) if not namespace: namespace = module_path prefix = f"{module_path}.") for pkg in walk_packages(module.__path__, prefix=prefix): finder, name, _ = pkg # pkgutil.ModuleInfo module = finder.find_module(name).load_module(name) view = getattr(module, "dispatch", None) route_name = name[len(prefix):] route = route_name.replace('.', '/') if callable(view): result.append(path(route, view, name=route_name)) result.sort(key=lambda x: str(x.pattern), reverse=True) return path("", include((result, namespace)))
urls.py
urlpatterns = [
fs_paths("myapp.views", "myapp"),
]
It "just works โข๏ธ"
# myapp/views/posts/slug.py
path = "posts/<slug:slug>"
def dispatch(request, slug):
...
# myapp/views/projects/id.py
path = "projects/<int:id>"
def dispatch(request, id):
...
route = route_name.replace('.', '/')
if callable(view):
result.append(path(route, view))
route = getattr(module, "path", route_name.replace('.', '/'))
if callable(view):
result.append(path(route, view, name=route_name))
# myapp/views/projects/id.py
path = "<int:id>"
def dispatch(request, id):
...
dispatch
?dispatch
?def dispatch(request, *args, **kwargs):
...
dispatch
?def get(request, *args, **kwargs):
...
def post(request, *args, **kwargs):
...
...
re_path = r"(?P<year>[0-9]{4})"
def dispatch(request, *args, **kwargs):
...
{ "name": "Sage Abdullah", "username": "laymonage", "slides": { "hosted": "https://slides.laymonage.com/fs-paths", "source": "https://github.com/laymonage/slides-fs-paths" }, "project": "https://github.com/laymonage/django-fs-paths", "alternative": "https://github.com/jerivas/django-file-router", "misc": { "jobs": "https://torchbox.com/careers", "wagtail": "https://wagtail.org" } }