Django - 获取反转url所需的参数名称

Posted

技术标签:

【中文标题】Django - 获取反转url所需的参数名称【英文标题】:Django - get names of parameters needed to reverse url 【发布时间】:2016-01-05 06:59:28 【问题描述】:

背景

假设我有一个带有参数的 url 模式,可以将我链接到 django 中的视图:

url(
    r'^things/(?P<thing_name>\w+)/features/(?P<feature_name>\w+)$',
    views.thingFeature,
    name='thing_feature'
),

假设我有一个thing 和一个feature

thing = Thing.objects.get(.....)
feature = thing.feature_set.first()

t_name = thing.name
f_name = feature.name

现在 Django 为我提供了获取 url 的强大功能,该 url 将我带到专门用于特定事物的特定功能的页面。我可以这样做:

from django.core.urlresolvers import reverse
url = reverse('thing_feature', thing_name=t_name, feature_name=f_name)
# url == '/things/thing2/features/left-arm'

问题

现在我偶然发现了一种需要专门解决的情况。我不是在寻找解决方法 - 我正在寻找解决以下问题:

给定一个 url 的 name,我如何获得反转该 url 所需的 kwarg 参数名称列表?

我正在寻找函数get_kwarg_names_for_url。它的行为是这样的:

url_kwarg_names = get_kwarg_names_for_url('thing_feature')
# url_kwarg_names == ['thing_name', 'feature_name']

url_kwarg_names 现在是我需要提供给 Django 的 reverse 函数以反转名为 "thing_feature" 的 URL 的每个关键字的列表。

感谢任何帮助!

解决方案

根据 knbk 的回答,我想出了以下解决方案:

def get_kwarg_names_for_url(url_name):
    resolver = get_resolver(get_urlconf())
    reverse_data = resolver.reverse_dict[url_name]

    pattern_list = reverse_data[0]

    '''
    Need to specify the 1st pattern because url regexes can
    potentially have multiple kwarg arrangments - this function does
    not take this possibility into account.
    ''' 
    first_pattern = pattern_list[0]

    '''
    `first_pattern` is now of the form `(url_string, kwarg_list)` -
    all we are interested in is the 2nd value.
    '''
    return first_pattern[1]

【问题讨论】:

我刚刚陷入了以下困境:反转 url,将 url 与 urlpattern 匹配,编译 urlpattern 正则表达式,并检查正则表达式的 groupindex... 我必须这里缺少一些东西。 一个问题是,在您已经知道所需的 url 参数名称之前,您无法反转 url - django 将为 reverse('thing_feature') 引发错误,因为它缺少所需的 kwargs! 你可以试试这个***.com/a/1275601 我在这里试过了,用.items() 代替,它会返回一个很好的包含kwargs 的元组列表。你必须更深入 github.com/django/django/blob/stable/1.8.x/django/core/…> 似乎是一个好的开始,不幸的是我现在要回家了,不能再深入了。 我只想补充一点,您不需要 kwarg 名称本身来反转模式。甚至具有命名组的模式也接受位置参数。 【参考方案1】:

我会从一个公平的警告开始:使用公共 API 是不可能的。最重要的是,我正在积极地为 1.10 重写 URL 调度程序,所以到那时这个方法很可能会中断。

首先,您需要获得正确的RegexURLResolver。如果视图不在命名空间中,您可以使用reverse_dict 获取可能性列表,并提取 kwargs:

def get_kwargs(view_name):
    resolver = urlresolvers.get_resolver()
    patterns = resolver.reverse_dict.getlist(view_name)
    kwargs = []
    for possibility, pattern, defaults in patterns:
        for result, params in possibility:
            kwargs.append(params)
    return kwargs

由于一个视图名称可以有多个具有不同 kwargs 的模式(尽管为了您自己的理智,您希望避免这种情况),这将返回每组可能的 kwargs 的列表。通常,不同的集合是一侧的必需 kwargs 和另一侧的必需 + 可选 kwargs。

我没有对此进行测试,但如果它不起作用,您可以在resolver.reverse_dict 中挖掘一下以找出确切的细节。它的设计并没有完全考虑到可用性。

【讨论】:

您先生是个野蛮人。你的代码不能直接工作,但它给了我足够多的信息来让它发挥作用。我也不担心 url 正则表达式会导致多个 kwarg 安排。更新了我的问题以反映最终的效果。 附注听起来你是 django 的作者之一? @GershomMaes 我是贡献者,但不是核心团队的一员;) 哦,coolcool,无论如何感谢您的出色回答!它会很好地为我服务:)【参考方案2】:

您应该可以通过resolve() 做到这一点

来自文档:

然后可以询问 ResolverMatch 对象以提供有关与 URL 匹配的 URL 模式的信息:

func, args, kwargs = resolve('/some/path/')

特定于您的示例代码:

url = reverse('thing_feature')
func, args, kwargs = resolve(url)
# args == ['thing_name', 'feature_name']

【讨论】:

以上是关于Django - 获取反转url所需的参数名称的主要内容,如果未能解决你的问题,请参考以下文章

获取带有名称的活动 URL 列表

Django:测试页面是不是已重定向到所需的 url

Django - 如何从多个模型中获取所需的数据

Django python:使用 DateInput -- 找不到所需的参数“年份”(位置 1)

反向 Django 管理 URL

从 Swift 2 迁移到 Swift 3 期间的奇怪问题:初始化程序的参数名称与协议所需的名称不同