如何获取Django应用程序中所有视图的列表?

frebpwbc  于 2023-03-24  发布在  Go
关注(0)|答案(4)|浏览(165)

有没有什么方法可以在django应用程序中获得所有视图的列表?我在谷歌上搜索了答案。所有答案都显示了一种获得URL列表的方法。

am46iovg

am46iovg1#

获取Django项目所有视图列表:

为了获取Django项目中存在的所有视图,我们创建了一个函数get_all_view_names(),它将urlpatterns作为输入,并将项目中使用的完整视图列表作为输出返回。
首先,我们使用settings.ROOT_URLCONF导入root_urlconf模块。然后root_urlconf.urls.urlpatterns将为我们提供项目的urlpatterns列表。
上面的urlpatterns列表包含RegexURLPatternRegexURLResolver对象。在RegexURLResolver上访问.urlpatterns将进一步为我们提供RegexURLPatternRegexURLResolver对象的列表。

**RegexURLPattern对象将给予我们感兴趣的视图名称。**其上的callback属性包含可调用视图。当我们在url中传递一个字符串(如'foo_app.views.view_name')表示模块的路径和视图函数名称时,或者传递一个可调用视图时,然后callback属性被设置为这个。进一步访问.func_name将给予我们视图名称。

我们递归调用函数get_all_view_names(),并将从RegexURLPattern对象获得的视图名称添加到全局列表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)

获取Django应用中所有视图列表:

要获取Django应用程序中所有视图的列表,我们将使用上面定义的get_all_view_names()函数。
我们将首先导入应用程序的所有urlpatterns,并将此列表传递给get_all_view_names()函数。

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为我们提供了my_app Django应用程序中所有视图的列表。

o0lyfsai

o0lyfsai2#

添加到Rahul的上述修复中,如果有人使用***Python3***,则需要使用__name__而不是func_name

...
            view_name = pattern.callback.__name__
...

否则,您将得到以下内容:

AttributeError: 'function' object has no attribute 'get_all_view_names'

(感谢www.example.com上的scipy-gitbothttps://github.com/scipy/scipy/issues/2101#issuecomment-17027406
作为替代,如果你不愿意使用全局变量,下面是我最终使用的:

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)

然后,您可以遍历all_views_list以获得过滤后的视图列表。

更新:2018年3月1日

在Django 2.0中,django.core.urlresolvers被移动到django.urlsRegexURLPatternRegexURLResolver被重命名为URLPatternURLResolver。所以你应该使用

from django.urls import URLResolver, URLPattern

代替

from django.core.urlresolvers import RegexURLResolver, RegexURLPattern

如果你使用Django 2。

roqulrg3

roqulrg33#

使用全局变量获取所有Django和DRF视图

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
xqk2d5yq

xqk2d5yq4#

我需要计算我的项目. Here's code that does that的本地视图数。
这与目前的答案不同,因为:

  • 它按视图对象而不是视图名称(可能与其他视图名称冲突)对视图进行分组
  • 不包括ModelAdmin类下的视图
  • get_all_local_views函数只返回当前目录(或settings.ROOT_DIR下)中不在venv目录下的视图
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))

相关问题