Last active
August 29, 2015 14:15
-
-
Save davidwtbuxton/045eff038c0bee38edff to your computer and use it in GitHub Desktop.
List all Django urls
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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