Skip to content

Instantly share code, notes, and snippets.

@jmduke
Created October 26, 2022 15:42
Show Gist options
  • Save jmduke/434739ebc4e2112397becfd403f2ecfd to your computer and use it in GitHub Desktop.
Save jmduke/434739ebc4e2112397becfd403f2ecfd to your computer and use it in GitHub Desktop.
Typescript-friendly replacement for `django-js-reverse`
from dataclasses import dataclass
from django.template.loader import render_to_string
from django.urls import URLResolver, get_resolver
@dataclass
class Route:
name: str
params: list[str]
template: str
def munge_template(raw_template: str, params: list[str]) -> str:
text = raw_template
for param in params:
text = text.replace(f"%({param})s", "${{{}}}".format(param))
return text
def extract_routes(resolver: URLResolver) -> list[Route]:
# A lot of this approach is borrowed from `django-urls-reverse`, just with a different
# way of munging the final routes.
keys = [key for key in resolver.reverse_dict.keys() if isinstance(key, str)]
key_to_route = {key: resolver.reverse_dict.getlist(key)[0][0][0] for key in keys}
return [
Route(key, key_to_route[key][1], munge_template(*key_to_route[key]))
for key in keys
]
def generate(urlconf: str) -> str:
default_urlresolver = get_resolver(urlconf)
routes = extract_routes(default_urlresolver)
return render_to_string("urls.ts.template", {"routes": routes})
const URLS = {{% for route in routes %}
'{{ route.name }}': ({% for param in route.params %}{{ param }}: string{% if not forloop.last%}, {% endif %}{% endfor %}) => `/{{ route.template }}`,{% endfor %}
};
export default URLS;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment