Is there any way to get a list of all views in an django app? I have googled for answer. All answers shows a way to get list of urls.
-
2[This](http://stackoverflow.com/a/1275601/192390) returns a list of _registered_ views. – Ivan Oct 04 '15 at 12:52
4 Answers
Getting list of all the views of a Django project:
To get all the views present in a Django project, we create a function get_all_view_names()
which takes urlpatterns
as input and returns the complete list of views being used in the project as the output.
First, we import the root_urlconf
module using settings.ROOT_URLCONF
. Then root_urlconf.urls.urlpatterns
will give us the list of project's urlpatterns.
The above urlpatterns list contains RegexURLPattern
and RegexURLResolver
objects. Accessing .urlpatterns
on a RegexURLResolver
will further give us a list of RegexURLPattern
and RegexURLResolver
objects.
A RegexURLPattern
object will give us the view name which we are interested in. The callback
attribute on it contains the callable view. When we pass either a string in our urls like 'foo_app.views.view_name'
representing the path to a module and a view function name, or a callable view, then callback
attribute is set to this. Further accessing .func_name
will give us the view name.
We call the function get_all_view_names()
recursively and add the view names obtained from a RegexURLPattern
object to a global list VIEW_NAMES
.
from django.conf import settings
from django.core.urlresolvers import RegexURLResolver, RegexURLPattern
root_urlconf = __import__(settings.ROOT_URLCONF) # import root_urlconf module
all_urlpatterns = root_urlconf.urls.urlpatterns # project's urlpatterns
VIEW_NAMES = [] # maintain a global list
def get_all_view_names(urlpatterns):
global VIEW_NAMES
for pattern in urlpatterns:
if isinstance(pattern, RegexURLResolver):
get_all_view_names(pattern.url_patterns) # call this function recursively
elif isinstance(pattern, RegexURLPattern):
view_name = pattern.callback.func_name # get the view name
VIEW_NAMES.append(view_name) # add the view to the global list
return VIEW_NAMES
get_all_view_names(all_urlpatterns)
Getting list of all the views in a Django application:
To get the list of all the views present in a Django application, we will use the get_all_view_names()
function defined above.
We will first import all the urlpatterns
of the application and pass this list to the get_all_view_names()
function.
from my_app.urls import urlpatterns as my_app_urlpatterns # import urlpatterns of the app
my_app_views = get_all_view_names(my_app_urlpatterns) # call the function with app's urlpatterns as the argument
my_app_views
gives us the list of all the views present in my_app
Django app.

- 46,769
- 10
- 112
- 126
Adding on to above fix by Rahul, if anyone is using Python3, you will need to use __name__
instead of func_name
:
...
view_name = pattern.callback.__name__
...
otherwise you will get the following:
AttributeError: 'function' object has no attribute 'get_all_view_names'
(Thanks to scipy-gitbot at https://github.com/scipy/scipy/issues/2101#issuecomment-17027406
As an alternative, if you are disinclined to using global variables, here is what I ended up using :
all_urlpatterns = __import__(settings.ROOT_URLCONF).urls.urlpatterns
detail_views_list = []
def get_all_view_names(urlpatterns):
for pattern in urlpatterns:
if isinstance(pattern, RegexURLResolver):
get_all_view_names(pattern.url_patterns)
elif isinstance(pattern, RegexURLPattern):
detail_views_list.append(pattern.callback.__name__)
get_all_view_names(all_urlpatterns)
all_views_list = []
# remove redundant entries and specific ones we don't care about
for each in detail_views_list:
if each not in "serve add_view change_view changelist_view history_view delete_view RedirectView":
if each not in all_views_list:
all_views_list.append(each)
Then you can just iterate through all_views_list
to get the list of filtered views.
update: Mar 1 2018
In Django 2.0, django.core.urlresolvers
is moved to django.urls
. RegexURLPattern
and RegexURLResolver
are renamed to URLPattern
and URLResolver
. So you should use
from django.urls import URLResolver, URLPattern
instead of
from django.core.urlresolvers import RegexURLResolver, RegexURLPattern
if you are using Django 2.
-
Here's updated code with both patches: https://pastebin.com/ALYJVgqE – Paul Schreiber Dec 21 '20 at 01:04
Get all Django and DRF views w/o using global vars
def get_all_views(urlpatterns, views=None):
views = views or {}
for pattern in urlpatterns:
if hasattr(pattern, 'url_patterns'):
get_all_views(pattern.url_patterns, views=views)
else:
if hasattr(pattern.callback, 'cls'):
view = pattern.callback.cls
elif hasattr(pattern.callback, 'view_class'):
view = pattern.callback.view_class
else:
view = pattern.callback
views[pattern.name] = view
return views

- 5,737
- 44
- 35
-
instead of `views = views or {}` use `views = views if views is not None or {}` – k4anubhav Dec 13 '22 at 14:41
I needed to count the number of views that were local to my project. Here's code that does that.
This differs from current answers because:
- It groups views by the view object rather than the view name (which could collide with other view names)
- Views that are under a
ModelAdmin
class are not included - The
get_all_local_views
function returns only the views within the current directory (or undersettings.ROOT_DIR
) that aren't under avenv
directory
from importlib import import_module
import inspect
from pathlib import Path
import importlib.util
from django.conf import settings
from django.contrib.admin.options import ModelAdmin
from django.urls import URLResolver, URLPattern
def is_modeladmin_view(view):
"""Return True if the view is an admin view."""
view = inspect.unwrap(view) # In case this is a decorated view
self = getattr(view, "__self__", None)
return self is not None and isinstance(self, ModelAdmin)
def get_all_views(urlpatterns):
"""Given a URLconf, return a set of all view objects."""
views = set()
for pattern in urlpatterns:
if hasattr(pattern, "url_patterns"):
views |= get_all_views(pattern.url_patterns)
else:
if hasattr(pattern.callback, "cls"):
view = pattern.callback.cls
elif hasattr(pattern.callback, "view_class"):
view = pattern.callback.view_class
else:
view = pattern.callback
if not is_modeladmin_view(view):
views.add(view)
return views
def get_module_path(module_name):
"""Return the path for a given module name."""
spec = importlib.util.find_spec(module_name)
if spec is None:
raise ImportError(f"Module '{module_name}' not found")
return Path(spec.origin).resolve()
def is_subpath(path, directory):
"""Return True if path is below directory and isn't within a "venv"."""
try:
path.relative_to(directory)
except ValueError:
return False
else:
# Return True if view isn't under a directory ending in "venv"
return not any(p.endswith("venv") for p in path.parts)
def get_all_local_views():
"""Return a set of all local views in this project."""
root_urlconf = import_module(settings.ROOT_URLCONF)
all_urlpatterns = root_urlconf.urlpatterns
try:
root_directory = settings.ROOT_DIR
except AttributeError:
root_directory = Path.cwd() # Assume we're in the root directory
return {
view
for view in get_all_views(all_urlpatterns)
if is_subpath(get_module_path(view.__module__), root_directory)
}
all_views = get_all_local_views()
print("Number of local views:", len(all_views))

- 10,975
- 4
- 55
- 114
-
This is the only answer that works with modern Django. The rest refer to URL resolver classes that don't exist anymore. – helmetwearer May 22 '23 at 19:02