在 Django 中,如何获取 URI 解析到的基于 class 的视图的实例?

In Django, how can I get an instance of the class-based-view that a URI resolves to?

我正在开发一个导航系统,我需要从指向它的 URI 中获取 class based view

我现在正在使用 resolve('/path/to/whatever/') 获取 ResolverMatch。 ResolverMatch 有一个字典项 func,它仅作为可调用函数而不是对象链接到 class based view

ResolverMatch(func=catalog.views.ThingDetail, args=(), kwargs={'id': '99'}, url_name=thing_detail, app_names=[], namespaces=[])

不过,我需要的是作为对象的对象。我正在通过使用 inspect 获取 func 方法的对象来破解它,但似乎应该有更好的方法。

以下应该可以让您获得视图 class 及其实例(如果需要):

import importlib

rm = resolve('/path/to/whatever/')  # ResolverMatch
module_name = rm.func.__module__  # 'path.to.views'
view_name = rm.func.func_name  #'FooView'

views = importlib.import_module(module_name)
# <module 'path.to.views' from '/path/to/project_root/path/to/views.pyc'>

view_klass = getattr(views, view_name)
# <class 'path.to.views.FooView'>

view_instance = view_klass()
# <path.to.views.FooView object at 0x7fe2219528d0>

但是请注意,不可能以这种方式获取将用于特定请求的实例,因为视图 ​​class 仅在 rm.func 时实例化 - 可调用 return by View.as_view() - 被调用。

摘自implementation of View

@classonlymethod
def as_view(cls, **initkwargs):
    ...
    def view(request, *args, **kwargs):
        # See: view cls is only instantiated when 'view' is called
        self = cls(**initkwargs)
        ...
        return self.dispatch(request, *args, **kwargs)
    ...
    return view

我发现有一个 属性 resolver_match.func.view_class,我可以调用 resolver_match.func.view_class() 来获取基于 class 的视图的实例。

感谢@schwobaseggl 指出 resolver_match.func 是一个具有属性的对象。具有 class function 的对象具有属性,这既奇怪又令人惊讶。