Skip to content

Instantly share code, notes, and snippets.

@davidwtbuxton
Last active August 29, 2015 14:15
Show Gist options
  • Save davidwtbuxton/045eff038c0bee38edff to your computer and use it in GitHub Desktop.
Save davidwtbuxton/045eff038c0bee38edff to your computer and use it in GitHub Desktop.
List all Django urls
# List all URLs in a Django application.
from collections import namedtuple
from django.conf.urls import RegexURLResolver, include
from django.views.generic import View
def walk_patterns(patterns, prefix=()):
"""Yields pairs of (RegexURLPattern, prefixes) where the first is the
pattern instance which has the actual view function, url name, etc. and the
second is a tuple of strings, the pattern prefixes from any includes.
"""
for pat in patterns:
if isinstance(pat, RegexURLResolver):
pat_prefix = prefix + (pat.regex.pattern,)
for pat in walk_patterns(pat.url_patterns, prefix=pat_prefix):
yield pat
else:
yield pat, prefix
def get_view(callback):
"""If this callback is a class-based as_view() function, returns the wrapped
view class. Else returns the callback.
"""
# Assumes Django's as_view() wrapper, which calls the class with 'cls()'.
# Should handle Python >= 2.7 including 3.x.
try:
arg_index = callback.__code__.co_freevars.index('cls')
except (AttributeError, ValueError):
# callback.__module__ should show where this function lives.
return callback
view_class = callback.__closure__[arg_index].cell_contents
return view_class if issubclass(view_class, View) else callback
ViewInfo = namedtuple('ViewInfo', ['prefix', 'pattern', 'name', 'view', 'callback'])
def new_view_info(pattern, prefix):
return ViewInfo(
view=get_view(pattern.callback),
callback=pattern.callback,
name=pattern.name,
prefix=prefix,
pattern=pattern.regex.pattern,
)
def list_urls(urlconf):
module, app_name, ns = include(urlconf)
urls = walk_patterns(module.urlpatterns)
return [new_view_info(pattern, prefix) for pattern, prefix in urls]
def pretty(info):
prefix = ''.join(pat[1:] for pat in info.prefix)
# Get the module.
return (prefix + info.pattern[1:], info.view, info.view.__module__, info.name)
def main(urlconf_name, out):
"""Write a CSV with all the URL paths found from the root urlconf module.
Use the string from your Django settings.ROOT_URLCONF, e.g. 'mysite.urls'.
"""
import csv
writer = csv.writer(out)
for info in list_urls(urlconf_name):
writer.writerow(pretty(info))
return 0
if __name__ == '__main__':
import sys
# Usage: python thisscript.py myproject.settings.urls > all-urls.csv
sys.exit(main(sys.argv[1], sys.stdout))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment